关于Stdcall,safecall等(20分)

  • 主题发起人 主题发起人 LoveBorland
  • 开始时间 开始时间
L

LoveBorland

Unregistered / Unconfirmed
GUEST, unregistred user!
我用Delphi写了一个DLL: 'MYDll2.DLL';
......

function MyPos(subs,s:String):integer;
begin
result:=Pos(subs,s);
end;

exports MyPos;

如果在应用程序中如此调用:
......
function MyPos(subs,s:String):integer;register;external 'MYDll2.DLL';
或function MyPos(subs,s:String):integer;external 'MYDll2.DLL';

......
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption:=IntToStr(MyPos('uubs','s'));
Button1.Caption:=IntToStr(MyPos('s','uubs'));
end;则分别返回正0和4;


如果在应用程序中如此调用:
......
function MyPos(subs,s:String):integer;stdcall;external 'MYDll2.DLL';
或function MyPos(subs,s:String):integer;safecall 'MYDll2.DLL';

......
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption:=IntToStr(MyPos('uubs','s'));
Button1.Caption:=IntToStr(MyPos('s','uubs'));
end;则都返回的是0.为什么?
SafeCall,StdCall,External不就是传递参数的顺序不一样吗?
 
>> SafeCall,StdCall,External不就是传递参数的顺序不一样吗?
^^^^^^^^ External 不是调用约定
register 和 stdcall 根本不一样:
register 使用寄存器 eax, edx, ecx 传递参数
stdcall 使用堆栈从右到左压栈传递参数

>> function MyPos(subs,s:String):integer;
缺省使用 register 调用协定,导入 DLL 时必须使用 相同的调用协定
 
External 是告诉编译器 外部函数来自什么文件;
safecall,stdcall,cdecl 的顺序是一样的(R to L),而 register 和pascal 是一样的(L to R)
 
虽然safecall,stdcall,cdecl 的顺序是一样的(R to L),
如果在应用程序中如此调用:
但按照如下申明和调用方式:
function MyPos(subs,s:String):integer;stdcall;external 'MYDll2.DLL';
或function MyPos(subs,s:String):integer;safecall 'MYDll2.DLL';

procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption:=IntToStr(MyPos('uubs','s'));
Button1.Caption:=IntToStr(MyPos('s','uubs'));
end;
为什么都返回的是0?按照我的理解
Label1.Caption:=IntToStr(MyPos('uubs','s'));的结果应是4呀

 
safecall一般是用于COM调用的,它可以自动检查返回HResult的函数是否返回错误码,如果是错误码就触发一个异常。只要不写COM一般不用safecall的。
大致上,safecall和stdcall的等价关系为:
procedure AProc(AParam: WideString);safecall;
相当于
function AProc(AParam: WideString): HResult;stdcall;
 
你定义的函数好像是fastcall,采用寄存器传递参数的呀
 
好像什么也不写就是默认的register调用方式
 
后退
顶部