大浪淘沙

dotNet技术讨论

导航

P/Invoke 回调函数指针的试验

有些API函数需要传进一个回调函数指针, 在.NET中可以传一个delegate过去, 不过.NET到底是如何辨别回调函数的调用约定呢? 虽然Window API的回调函数都是以stdcall来声明, 但也不代表所有的都是这样, 比如, 我写个比较离经判道的Win32代码:

library CBDll;

uses
  SysUtils,
  Classes;

{$R *.res}

type
  TMyCallBackFunc1 = procedure (P1: Integer; P2: Integer); stdcall;

  TMyCallBackFunc2 = procedure (P1: Integer; P2: Integer); pascal;

procedure DoCallBack1(Proc: TMyCallBackFunc1); stdcall;
begin
  Proc(1, 2);
end;

procedure DoCallBack2(Proc: TMyCallBackFunc2); stdcall;
begin
  Proc(1, 2);
end;

exports
  DoCallBack1,
  DoCallBack2;

begin
end.


然后在另一个.net项目中使用这个DLL
type
  TMyCallBackFunc1 = procedure (P1: Integer; P2: Integer);
  TMyCallBackFunc2 = procedure (P1: Integer; P2: Integer);

procedure DoCallBack1(Proc: TMyCallBackFunc1); external 'CBDll.dll';

procedure DoCallBack2(Proc: TMyCallBackFunc2); external 'CBDll.dll';

procedure CallBack1(P1: Integer; P2: Integer);
begin
  ShowMessageFmt('%d, %d', [P1, P2]);
end;

procedure CallBack2(P1: Integer; P2: Integer);
begin
  ShowMessageFmt('%d, %d', [P1, P2]);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoCallBack1(@CallBack1);
  DoCallBack2(@CallBack2);
end;

DoCallBack1是使用调用约定为stdcall的回调函数指针, 而DoCallBack2使用pascal,  两种调用约定不同之处在于pascal的参数入栈顺序按语法声明顺序从左到右依次入栈, 而stdcall与之相反, 结果DoCallBack1弹出的消息是"1, 2", DoCallBack2弹出的消息是"2, 1", 可见.NET P/Invoke处理回调只处理了stdcall这一种类型

posted on 2006-08-12 20:27  大浪淘沙Shen  阅读(635)  评论(2)    收藏  举报