我想在 Delphi中使用來自kaoh Karsten Ohme的 GlobalPlatform.dll。所以我試圖翻譯標題,這樣我就可以在 Delphi 中使用 GlobalPlatform.dll。
我翻譯的第一個是 Connection.h,我把它上傳到了 pastebin 這里。
我翻譯的第二個是 Security.h我把它上傳到了 pastebin 這里。
首先,我用函式建立了一個背景關系OPGP_establish_context,這似乎沒問題,因為結果是 aOPGP_ERROR_STATUS_SUCCESS并且訊息也表明“成功”。
但隨后我嘗試使用該函式列出讀者,該OPGP_list_readers函式也回傳成功 - 但是當我嘗試讀取回傳的名稱時,我會遇到各種訪問沖突(主要是在adress 00000000 and trying to read 00000000,但我的嘗試之間存在差異)。
我的代碼被分配給一個按鈕點擊:
procedure TfrmFormatCard.Button1Click(Sender: TObject);
const
BUFLEN = 1024;
var
Status,
Status2 : OPGP_ERROR_STATUS;
Context : OPGP_CARD_CONTEXT;
Names : array [0..BUFLEN 1] of Char;
Len : DWord;
begin
Context.libraryName := 'gppcscconnectionplugin';
Context.libraryVersion := '211';
Status := OPGP_establish_context(Context);
if Status.errorStatus = OPGP_ERROR_STATUS_SUCCESS then
begin
Len := 1024;
Status2 := OPGP_list_readers(Context, Names, Len);
if Status2.errorStatus = OPGP_ERROR_STATUS_SUCCESS then
begin
// Messagebox(application.Handle, names, '', 0);
end;
OPGP_release_context(Context);
end;
end;
當我使用上面的代碼時,我沒有收到任何錯誤,但是當我取消注釋訊息框時 - 我得到了訪問沖突。我整天都在嘗試,我修改了所有內容..但沒有運氣。我看不出我做錯了什么。也許有人可以幫助我并指出正確的方向。我了解訪問沖突adress 00000000意味著什么,但我不知道我是否以正確的方式翻譯了標題,這可能會導致錯誤。
如果有人可以通過自己檢查或測驗來幫助我 - 那將不勝感激。
我正在使用 Delphi 10.4,并且我有一個內部智能卡讀卡器(在筆記本電腦中)、一個 Omnikey 智能卡讀卡器和另一個未知品牌。
附言。是的,我知道 GPSShell 命令列實用程式,但我想避免使用它。我想使用智能卡來保證安全性,而對命令列工具的需求會使這成為一個弱點——因此我想直接使用庫。
uj5u.com熱心網友回復:
在您翻譯的第一條記錄中OPGP_ERROR_STATUS,該errorMessage欄位在 C 代碼中宣告為:
TCHAR errorMessage[ERROR_MESSAGE_LENGTH 1];
其中ERROR_MESSAGE_LENGTH定義為 256,因此該陣列最多有257 個字符。
但是你的翻譯:
errorMessage : array [0..ERROR_MESSAGE_LENGTH 1] of Char;
最多258 個字符。這是因為Delphi 中的陣列宣告定義了陣列的索引,包括在內,因此在您的情況下,您將陣列宣告為具有索引0..257,但它應該是0..256,所以洗掉 1:
errorMessage : array [0..ERROR_MESSAGE_LENGTH] of Char;
您在翻譯OPGP_CARD_CONTEXT記錄時也犯了同樣的錯誤:
OPGP_CARD_CONTEXT = record
librarySpecific : Pointer;
libraryName : array [0..64] of Char; // <--
libraryVersion : array [0..32] of Char; // <--
libraryHandle : Pointer;
connectionFunctions : OPGP_CONNECTION_FUNCTIONS;
end;
您宣告libraryName有65 個字符和33 個libraryVersion字符。它們需要分別為64和32:
OPGP_CARD_CONTEXT = record
librarySpecific : Pointer;
libraryName : array [0..63] of Char;
libraryVersion : array [0..31] of Char;
libraryHandle : Pointer;
connectionFunctions : OPGP_CONNECTION_FUNCTIONS;
end;
根據原始 C 宣告:
typedef struct {
PVOID librarySpecific; //!< Library specific data.
TCHAR libraryName[64]; //!< The name of the connection library to use.
TCHAR libraryVersion[32]; //!< The version of the connection library to use.
PVOID libraryHandle; //!< The handle to the library.
OPGP_CONNECTION_FUNCTIONS connectionFunctions; //!< Connection functions of the connection library. Is automatically filled in if the connection library can be loaded correctly.
} OPGP_CARD_CONTEXT;
因此,為什么會發生 AV 是有道理的,因為OPGP_list_readers()內部訪問存盤在Context.connectionFunctions陣列后面的欄位中的函式指標,因此將在錯誤的記憶體偏移量處訪問指標。
其他需要注意的是TCHAR,它將映射到char或wchar_t取決于 DLL 的實際編譯方式。因此,這可能會或可能不會轉化為CharDelphi,具體取決于您使用的版本(您沒有說)。一般來說,char-> AnsiChar,wchar_t-> WideChar。該專案的unicode.h檔案建議編譯非 Windows 版本以使用char. 但是專案 makefile 建議編譯 Windows 版本以wchar_t代替使用。(P)Char因此,在互操作代碼中使用不是一個好主意。根據需要使用(P)AnsiChar或(P)WideChar代替。
更新
另外,Context在將其傳遞給OPGP_establish_context(). 內部做的第一件事OPGP_establish_context()是呼叫OPGP_release_context(),Context這意味著其中Context不能包含任何垃圾(特別是在libraryHandleandconnectionFunctions.releaseContext欄位中),否則它將被錯誤處理。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/460937.html
