在使用一个dll时,一个接口需要传递一个回调函数指针进去
而用普通函数和类的静态函数传进去确得到不同的结果
函数声明分别为
class procedure Port.GlobalDataArrived(port :Integer);stdcall;
procedure GlobalDataArrived(port :Integer);stdcall;
函数主要内容如下
var
port1 :Integer;
begin
port1 :=port;
end;在回调时类静态函数却产生错误的结果
反编译如下
class procedure Port.GlobalDataArrived(port :Integer);stdcall;
begin:
push ebp
mov ebp,esp
add esp,-$0c
push ebx
push esi
mov eax,[ebp+$0c]
mov [ebp-$0c],eax
.....procedure GlobalDataArrived(port :Integer);stdcall;
begin:
push ebp
mov ebp,esp
add esp,-$0c
push ebx
push esi
mov eax,[ebp+$08]
mov [ebp-$0c],eax
.....类的静态函数就不可以做回调函数吗?

解决方案 »

  1.   

    如果你非要传静态函数进去,那么就请改回调函数定义
    type
    TOnDataArrive = procedure (port: Integer) of object; stdcall;
      

  2.   

    问题是这个回调是通过调用dll接口函数传过去的函数指针方式如下
    RegisterCallBack(@Port.GlobalDataArrived);dll 在调用回调函数前将port参数压入栈中
    进入回调函数时port的参数的offset 应该在 [ebp+$08]位置
    如果是普通函数port的取值正确是从[ebp+$08]取出,结果正常
    如果是类的静态函数port的值是从[ebp+$0c]中取出,结果错误个人感觉问题出在类静态函数本身的修饰上,而不是传入指针的修饰上
    因为问题不是函数指针出的问题,静态函数能够被dll调用,只是在从栈中取参数时偏移不对,所以应该是回调函数本身编译的问题解决方法倒是有,定义一个普通函数做为回调函数,再从普通函数调用静态函数就能解决
      

  3.   

    因为静态函数还是隐含的传了一个类指针,因为你是stdcall传参,所以第一个参数就是隐含的类指针。
      

  4.   

    的确如此,delphi自己调用静态函数时先将参数倒着压入栈,最后压个类的指针
    而DLL只压参数,所以参数位置就偏移了4个字节