指向Delphi中C++typedef回调过程的指针

Pointer to a C++ typedef callback procedure in Delphi

本文关键字:过程 指针 回调 C++typedef Delphi 指向      更新时间:2023-10-16

从C++DLL 调用Delphi中的回调函数

我遇到了一个类似的错误,但是我的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;

仍然不起作用。

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。考虑第一个参数。那是一个非类型化的指针。单一级别的间接性。您将其声明为指针,通过引用传递。换句话说,两个层次的间接性。

对于CCD_ 2。这是一个由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);

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

最后一点我再怎么强调也不为过。你对这里细节的关注一直很弱。您发布的代码没有编译,并且使用了不一致的名称。这是一个地方的一个名字,然后在另一个地方用不同的名字。Interop就是关于细节的。你必须更加注意他们。