【问题标题】:Pointer to a C++ typedef callback procedure in DelphiDelphi 中指向 C++ typedef 回调过程的指针
【发布时间】:2014-10-01 15:57:04
【问题描述】:

Calling a callback function in Delphi from a C++ DLL

我遇到了类似的错误,但是我的 C++ 声明有点不同。

typedef int __stdcall CALLBACK(void* pP1, int I1, unsigned char* pUC,
    int I2, int I3, int I4, void* pP2);

我转换成的:

type TCALLBACK = function(var pP1: Pointer; var I1: integer;
    var pUC: PChar; var I2: Integer; var I3: Integer; var I4: Integer;
    var pP2: Pointer): Integer cdecl stdcall;

函数引用回调函数:

int MyFunction(void* pP1, TCALLBACK* pCallback, void* pP2);

我转换成的:

MyFunction: function(pP1: Pointer; var pCallBack: Pointer;
    pP2: Pointer): Integer cdecl stdcall;

调用函数:

var P : Pointer;
begin
    //Addr
    P := Addr(PCALLBACK); //had this as @PCALLBACK
    UFS_StartCapturing(ScannerHandle, P, self);
end;

Delphi 中声明的回调函数为:

function MyCallback(var pP1: Pointer; var I1: integer; var pUC: PChar;
    var I2: Integer; var I3: Integer; var I4: Integer;
    var pP2: Pointer): Integer;
var
    MainForm : TfrmMain;
begin
    //Do your thing
end;

我知道我的问题在于指向回调 (CALLBACK*) 的指针,现在正在尝试:

ADRESSOFCALLBACK= ^TCALLBACK;

MyFunction: function(pP1: Pointer; var pCallBack: ADRESSOFCALLBACK;
    pP2: Pointer): Integer cdecl stdcall;

还是不行。

【问题讨论】:

    标签: c++ delphi dll


    【解决方案1】:

    这个

    typedef int __stdcall CALLBACK(void* pP1, int I1, unsigned char* pUC, int I2, int I3, 
        int I4, void* pP2);
    

    翻译成

    type 
      TCALLBACK = function(pP1: Pointer; I1: integer; pUC: PByte; I2, I3, I4: Integer; 
          pP2: Pointer): Integer; stdcall;
    

    您误用了var。考虑第一个参数。那是一个无类型的指针。单层间接。您将其声明为指针,通过引用传递。换句话说,两个级别的间接性。

    至于unsigned char*。假设这是一个 8 位值的数组。按照惯例,char 用于文本,unsigned char 用于二进制数据。所以我认为unsigned char*是一个字节数组。

    这个

    int MyFunction(void* pP1, TCALLBACK* pCallback, void* pP2);
    

    翻译成

    MyFunction: function(pP1: Pointer; pCallBack: Pointer; pP2: Pointer): Integer; cdecl;
    

    但是,回调和函数使用不同的调用约定很奇怪。您确定没有在 C++ 代码中省略__stdcall

    现在看看你是怎么称呼它的:

     var
       P : Pointer;
     begin
       //Addr
       P := Addr(PCALLBACK); //had this as @PCALLBACK
       MyFunction(ScannerHandle, P, self);
     end;
    

    使用Addr 并将回调转换为无类型指针是一场灾难。编译器可以检查您是否传递了具有正确签名的回调。但是如果你把回调变成一个无类型参数,编译器就帮不了你了。所以,写成这样:

     MyFunction(ScannerHandle, MyCallback, self);
    

    其中MyCallback 是回调函数。我不知道PCALLBACK 是什么。

    最后一点,我强调的不够强烈。你对这里细节的关注很弱。您发布了未编译的代码,并且使用了不一致的名称。那是在一个地方有一个名字,然后在其他地方有一个不同的名字。互操作是关于细节的。您必须更加关注它们。

    【讨论】:

    • PCALLBACK 应该是 MyCallback。我不得不重命名一些名称,因为头文件的分发者不允许公开发布他们的头源代码。
    • 当我添加 MyFunction(ScannerHandle, MyCallback, self) 然后编译器给我 E2033 实际和正式 var 参数的类型必须相同,因为它需要一个指针。
    • 请在我的回答中使用代码。您的错误消息暗示在 MyFunction 中使用了 var 参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多