C回调函数在对象Pascal上崩溃

时间:2018-09-19 06:09:10

标签: 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

乐趣实现为:

void fun(void(*status_callback)(int)) {
   status_callback(0);
}

在如下所示的带有delphi xe的对象pascal上使用此dll时,在回调函数的地址处发生访问冲突崩溃

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

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

begin
 _fun(BCallBack);
end;

验证码:

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

出了什么问题?由于我是C语言的入门者?

1 个答案:

答案 0 :(得分:6)

我们缺少重要的细节。在C ++方面,我们看不到fun的实现,在Delphi方面,我们也看不到如何声明_fun

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

同样,我希望您的Delphi代码将_fun的调用约定错误。同样,它应该是cdecl,但错误消息表明您的声明实际上是register

总而言之,对您的Delphi代码进行以下更改:

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

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

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

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