Delphi向C++ DLL传递函数指针后调用参数异常问题排查
问题根源:调用约定不匹配
你的问题出在Delphi和C++两端的函数调用约定不一致,导致参数传递机制冲突,进而读取到错误的参数值。
具体修改方案
C++端代码调整
需要明确指定函数指针的调用约定为_stdcall,和setFoo本身的调用约定保持一致:
void (_stdcall *foo)(int); extern "C" void _stdcall setFoo(void (_stdcall *foo2)(int)) { foo = foo2; foo(1); }
Delphi端代码调整
- 把
TFoo类型和fooH函数都指定为stdcall调用约定,和C++端匹配; - 确保
TSetFoo的参数类型和调整后的TFoo一致:
TFoo = procedure(val: integer); stdcall; TSetFoo = procedure(val: TFoo); stdcall; ... Foo: TFoo; SetFoo:TSetFoo; ... procedure fooH(val: integer); stdcall; begin ShowMessage('foo '+IntToStr(val)); end; ... setFoo(fooH);
为什么这样改?
- Delphi默认的过程调用约定是
register,会用EAX、EDX、ECX寄存器传递前三个参数; - C++中未指定调用约定的函数指针默认是
cdecl,而你的setFoo用的是_stdcall,stdcall会通过栈传递所有参数,且由被调用者负责清理栈; - 两者调用约定不匹配时,参数传递的位置完全错位,C++端调用时读取到的是栈上的垃圾数据,所以会显示巨大的数值。
内容的提问来源于stack exchange,提问作者vico
相关产品推荐
相关产品推荐

