大浪淘沙

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 大浪淘沙 阅读(294) 评论(2) 编辑 收藏

评论

#1楼 2006-08-13 09:44 aspnetx      

如果您的代码能在webform下成功我拜您为师  回复 引用 查看   

#2楼[楼主] 2006-08-13 16:10 大浪淘沙      

@aspnetx
webform下为什么就不能成功?您试过了吗?
当然,showMessage是不能在webform下使用的:D
 回复 引用 查看