2014-10-01 90 views
-2

Calling a callback function in Delphi from a C++ DLL指针在Delphi

我坐在一个类似的错误一个C++的typedef回调过程不过我的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; 

回调函数:

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; 

还没加工。

回答

3

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是什么。

最后一点,我不能强调足够强调。你对这里的细节的关注一直很弱。您发布了未编译的代码,并使用了不一致的名称。这是一个地方的名字,然后是其他地方的另一个名字。 Interop是所有关于细节的。你必须更加关注他们。

+0

PCALLBACK应该是MyCallback。我不得不重新命名一些名称,因为头文件的发布者不允许公开发布它们的头源代码。 – StefandB 2014-10-01 16:43:03

+0

当我添加MyFunction(ScannerHandle,MyCallback,self)时,编译器会给我E2033实际和正式var参数的类型必须相同,因为它需要一个指针。 – StefandB 2014-10-01 17:22:26

+0

请使用我的答案中的代码。您的错误消息意味着在MyFunction中使用var参数。 – 2014-10-01 17:54:51