我想在德尔菲使用来自卡斯滕·奥姆的卡斯滕·奥姆。所以我试着翻译标题,这样我就可以在Delphi中使用GlobalPlatform.dll了。
我翻译的第一个是Connection.h,我把它上传到了这里。
我翻译的第二个是Secity.H 我把它上传到了这里。
首先,我用OPGP_establish_context函数建立了一个上下文,这似乎没问题,因为结果是一个OPGP_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智能卡阅读器,和另一个不知名的品牌。
ps。是的,我知道GPShell命令行实用程序,但我想避免使用它。我想使用智能卡来实现安全,而对命令行工具的需求将使这成为一个弱点--因此我想直接使用Library。
发布于 2022-04-07 21:24:17
在您翻译的第一条记录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个字符,libraryVersion具有33个字符。它们需要分别为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的实际编译方式。因此,根据您所使用的版本(您没有说出来),这可能会或不可能翻译成德尔菲中的Char。一般为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()内部所做的第一件事是在Context上调用OPGP_release_context(),这意味着Context不能在其中包含任何垃圾(特别是在libraryHandle和connectionFunctions.releaseContext字段中),否则它将被错误地处理。
https://stackoverflow.com/questions/71788620
复制相似问题