c++ - Delphi的回调函数在c中的使用方法

标签 c++ delphi callback

我有一个用 delphi 编写的 dll,它导出如下函数

function LaneController_Init(OnIOChangeEvent:TOnIOChangeEvent):Integer; stdcall;

OnIOChangeEvent是回调函数,propertype是

TOnIOChangeEvent = procedure(sender:TObject;DeviceID,iFlag:Integer) of object;

现在我的问题是在C++中,如何定义回调函数TOnIOChangeEvent

非常感谢。

最佳答案

您的 DLL 使用 Delphi 的两个截然不同的特性,只有 C++Builder 支持,其他 C++ 编译器不支持:

  1. 您的回调使用了 of object 修饰符,这意味着可以为回调分配一个对象实例的非静态方法。这是在 C++Builder 中使用供应商特定的 __closure 编译器扩展实现的。尽管标准 C++ 确实有使用指向对象方法的函数指针的语法,但其实现方式与 __closure 的实现方式有很大不同。

  2. 您的回调未声明任何调用约定,因此正在使用 Delphi 的默认 register 调用约定。在 C++Builder 中,这对应于特定于供应商的 __fastcall 调用约定(不要与 Visual C++ 的 __fastcall 调用约定混淆,后者完全不同,并且在 C++Builder 中作为 __msfastcall 实现)。

如果您只关心支持 C++Builder,那么您可以保留 DLL 代码,相应的 C++ 代码如下所示:

typedef void __fastcall (__closure *TOnIOChangeEvent)(TObject *Sender, int DeviceID, int iFlag);
int __stdcall LaneController_Init(TOnIOChangeEvent OnIOChangeEvent);

void __fastcall TSomeClass::SomeMethod(TObject *Sender, int DeviceID, int iFlag)
{
    //...
}

TSomeClass *SomeObject = ...;
LaneController_Init(&(SomeObject->SomeMethod));

但是,如果你需要支持其他的C++编译器,那么你需要修改DLL来支持标准的C/C++,例如:

type
  TOnIOChangeEvent = procedure(DeviceID, iFlag: Integer; UserData: Pointer); stdcall;

function LaneController_Init(OnIOChangeEvent: TOnIOChangeEvent; UserData: Pointer): Integer; stdcall;

然后你可以在 C++ 中执行以下操作:

typedef void __stdcall (*TOnIOChangeEvent)(int DeviceID, int iFlag, void *UserData);
int __stdcall LaneController_Init(TOnIOChangeEvent OnIOChangeEvent, void *UserData);

void __fastcall TSomeClass::SomeMethod(int DeviceID, int iFlag)
{
    //...
}

// note: not a member of any class. If you want to use a class
// method, it will have to be declared as 'static'...
void __stdcall LaneControllerCallback(int DeviceID, int iFlag, void *UserData)
{
    ((TSomeClass*)UserData)->SomeMethod(DeviceID, iFlag);
}

TSomeClass *SomeObject = ...;
LaneController_Init(&LaneControllerCallback, SomeObject);

关于c++ - Delphi的回调函数在c中的使用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20099393/

相关文章:

delphi - Delphi中的拼写校正器代码?

javascript - 如何在 Promise 中实现回调以使用 Mocha 和 Sinon 进行测试?

android - 如何收听哪个应用程序已被选为启动器应用程序?

delphi - 加入剪贴板链最佳实践

ios - 我如何强制方法等待回调在 swift 上完成?

c++ - 套接字聊天系统 - 将它们广播给所有客户端

c++ - 没有分号的程序在 C 中编译得很好,而不是在 C++ 中为什么?

c++ - 在 Linux 中编译/链接多个 C++ 库

c++ - `auto` 引用的说明符类型推导

delphi - 带 SSL 的 TCP/IP - Delphi 和 Indy10