对象pascal上的C回调函数崩溃

Kri*_* CN 6 c++ delphi

我正在创建一个像下面的C dll.

#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
    /* fun accept an argument status_callback which is a function pointer*/
    TEST_API void fun(void(*status_callback)(int));
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

和乐趣实现为:

void fun(void(*status_callback)(int)) {
   status_callback(0);
}
Run Code Online (Sandbox Code Playgroud)

在对象pascal上使用这个dll与delphi xe如下所示我在回调函数的地址遇到了访问冲突的崩溃

type
 TStatusCallBack = procedure( Value: Integer ); stdcall;
 T_fun = procedure(cb : TStatusCallback );

procedure BCallBack( Value: Integer ); stdcall;
begin
   BStatus := value;
end;

begin
 _fun(BCallBack);
end;
Run Code Online (Sandbox Code Playgroud)

实例化代码:

DLLHandle := LoadLibrary( ‘mylib.dll’ );
if (DLLHandle > HDLL_ERROR) then
begin
  _fun := T_fun(GetProcAddress( DLLHandle, 'fun');
end;
Run Code Online (Sandbox Code Playgroud)

有什么问题?既然我是C的noobie任何评论?

Dav*_*nan 5

我们缺少重要的细节.我们看不到funC++方面的实现,也看不出你_fun在Delphi方面的声明.

但是我们可以看到一个错误.回调的调用约定不匹配.C++代码将回调定义为__cdecl.您需要使用cdecl在Delphi端匹配,而不是stdcall.

同样地,我希望你的Delphi代码得到错误的调用约定_fun.它应该是,cdecl但错误信息表明您的声明实际上register.

总之,对Delphi代码进行以下更改:

  • 将回调函数类型声明为cdecl.
  • 声明实现回调的函数cdecl.
  • 声明导入funcdecl.

查看您的编辑,检查返回值的LoadLibrary错误是错误的.返回值为零表示错误.比较等于零以测试失败.

调用时也无法检查错误GetProcAddress.您需要处理nil返回的情况.同样,这可能会导致运行时出现错误,并且代码已写入.

编辑中的代码显示我的所有猜测都是正确的.解决方案详见上述要点.