首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将GlobalPlatform从C转换为Delphi违规错误

将GlobalPlatform从C转换为Delphi违规错误
EN

Stack Overflow用户
提问于 2022-04-07 20:36:16
回答 1查看 93关注 0票数 0

我想在德尔菲使用来自卡斯滕·奥姆卡斯滕·奥姆。所以我试着翻译标题,这样我就可以在Delphi中使用GlobalPlatform.dll了。

我翻译的第一个是Connection.h,我把它上传到了这里

我翻译的第二个是Secity.H 我把它上传到了这里。

首先,我用OPGP_establish_context函数建立了一个上下文,这似乎没问题,因为结果是一个OPGP_ERROR_STATUS_SUCCESS,消息还声明“成功”。

但是,我尝试用OPGP_list_readers函数列出读取器,它也会返回一个成功的结果--但是当我试图读取返回的名称时,我会得到各种访问违规行为(主要是在adress 00000000 and trying to read 00000000,但在尝试之间也有不同的地方)。

我的代码被分配给一个按钮单击:

代码语言:javascript
复制
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。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-07 21:24:17

在您翻译的第一条记录OPGP_ERROR_STATUS中,errorMessage字段在C代码中声明为:

代码语言:javascript
复制
TCHAR errorMessage[ERROR_MESSAGE_LENGTH+1];

其中ERROR_MESSAGE_LENGTH被定义为256个,因此该数组具有257个字符最大值。

但是你的翻译:

代码语言:javascript
复制
errorMessage : array [0..ERROR_MESSAGE_LENGTH + 1] of Char;

258个字符的最大值。这是因为Delphi中的数组声明定义了数组的索引(包括索引),所以在您的示例中,您将数组声明为具有索引0..257,但是它应该是0..256,所以删除+1

代码语言:javascript
复制
errorMessage : array [0..ERROR_MESSAGE_LENGTH] of Char;

您在翻译OPGP_CARD_CONTEXT记录时也犯了同样的错误:

代码语言:javascript
复制
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个字符。它们需要分别为6432

代码语言:javascript
复制
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声明原件:

代码语言:javascript
复制
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,它将映射到charwchar_t,具体取决于DLL的实际编译方式。因此,根据您所使用的版本(您没有说出来),这可能会或不可能翻译成德尔菲中的Char。一般为char -> AnsiCharwchar_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不能在其中包含任何垃圾(特别是在libraryHandleconnectionFunctions.releaseContext字段中),否则它将被错误地处理。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71788620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档