我有一个用 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++ 编译器不支持:
您的回调使用了
of object
修饰符,这意味着可以为回调分配一个对象实例的非静态方法。这是在 C++Builder 中使用供应商特定的__closure
编译器扩展实现的。尽管标准 C++ 确实有使用指向对象方法的函数指针的语法,但其实现方式与__closure
的实现方式有很大不同。您的回调未声明任何调用约定,因此正在使用 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/