关于李维一书中介绍接口一节的问题,请高手帮忙解释一下蓝色部分(参数是怎么与函数进行关联的)? (100分)

  • 主题发起人 主题发起人 一伊
  • 开始时间 开始时间

一伊

Unregistered / Unconfirmed
GUEST, unregistred user!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,TypInfo,IntfInfo;
type
{$M+}
ITestInterface=Interface
['{F3338FF9-C31C-43D8-8C39-754E7A39DBDD}']
function SayHello(s:String): String;stdcall;
function SayHello2(s:String;v:Integer;var sv:String):String;stdcall;
end;
{$M-}
TInvokerTest=Class(TInterfacedObject,ITestInterface)
private
FStr: String;
public
function SayHello(s: String):String;stdcall;
function SayHello2(s: String;v:Integer;var sv:String):String;stdcall;
end;

TMainForm = class(TForm)
ListBox1: TListBox;
Button1: TButton;
Button2: TButton;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
procedure Invoker;stdcall;
function GetCallPointer(vObj: TObject;MethodName: String):Pointer;
end;

var
MainForm: TMainForm;
CallSelf: Pointer;
CallAddr: Pointer;
Params: array of Pointer;
RetParam: Integer;
InterfaceInfo: PTypeInfo;
procedure ptRegisterInvokableInterface(AInterfaceInfo: PTypeInfo);
implementation
{$R *.dfm}
procedure ptRegisterInvokableInterface(AInterfaceInfo: PTypeInfo);
begin
InterfaceInfo:=AInterfaceInfo;
end;

function TMainForm.GetCallPointer(vObj: TObject;MethodName: String):Pointer;
function GetMethodIndex: Integer;
Var
IntfData: TIntfMetaData;
I,MethodIndex: Integer;
begin
GetIntfMetaData(InterfaceInfo,IntfData);

MethodIndex:=-1;
for I:=0 to High(IntfData.MDA)do
begin
if IntfData.MDA.Name=MethodName then
begin
MethodIndex:=I;
break;
end;
end;
Result:=MethodIndex;
end;
Var
MethodIndex: Integer;
TypeData: PTypeData;
pIntf: Pointer;
begin
MethodIndex:=GetMethodIndex;
if MethodIndex=-1 then
Result:=nil;

TypeData:=GetTypeData(InterfaceInfo);
if Supports(vObj,TypeData.Guid,pIntf) then
Result:=PPointer(Integer(Pointer(pIntf)^)+12+(MethodIndex*4))^;
end;

//////////////////////////////////////////////
//蓝色开始位置!
//////////////////////////////////////////////
[blue]procedure TMainForm.Invoker;
Var
I,Max: Integer;
ExBp: Integer;
asm
mov eax,[Params];
Call System.@DynArrayHigh;
test eax,eax;
jl @L2;
inc eax;
mov [Max],eax;
mov ,$00000000;
@L1:
mov eax,[Params];
mov edx,;
mov eax,[eax+edx*4];
push [eax];
inc dword ptr ;
dec dword ptr[Max];
jnz @L1;
@L2:
push CallSelf;
push [RetParam];
Call [CallAddr];
@L3:
end;
[/blue]
//////////////////////////////////////////////
//蓝色结束位置! 谢谢了
//////////////////////////////////////////////
function TInvokerTest.SayHello(s:String):string;
begin
FStr:=s;
ShowMessage(s);
Result:='Hello! I am Return';
end;
function TInvokerTest.SayHello2(s:string;v:Integer;var sv:string):string;
begin
ShowMessage(s);
Result:='test';
end;

procedure TMainForm.Button2Click(Sender: TObject);
Var
s,s1: String;
vCall: Pointer;
vObj: TInvokerTest;
p2: Pointer;
begin
s:='Hello Param';
s1:='ddsfjk';
SetLength(Params,1);
Params[0]:=@s;
RetParam:=Integer(@s1);
vObj:=TInvokerTest.Create;
CallAddr:=GetCallPointer(vObj,'SayHello');
CallSelf:=Pointer(Integer(Pointer(vObj))+16);
Invoker;
Showmessage(Pchar(Pointer(RetParam)^));
end;

Initialization
ptRegisterInvokableInterface(TypeInfo(ITestInterface));
end.
 
还没人回答,是分少的话可以再加呀。
 
这是一段汇编程序,我也是现在才知道原来Delphi可以这样用?到底什么问题?
 
Call [CallAddr]
该句是调用函数SayHello,调用SayHello要传一个参数(从执行结果,可知Params所指向的值,为该函数的参数值)。我想问的是,也是想要大家帮我解释的是:从这段汇编程序哪里可以看出:Params所指向的值,为该函数的参数值?它们是怎样进行关联起来的??
 
//Params[0]:=@s;
这里不是赋了值吗,通过这个全局数组传递啊
另可参见:http://www.delphibbs.com/delphibbs/dispq.asp?lid=1289838
 
Params[0]:=@s;
//是赋值,我之前看出来了
之前,不知道的是:汇编执行函数SayHello时,它会自动到相应的寄存器或堆栈中去取值(所以在这个地方被卡住了)。你所说的:对于一般的函数或过程,前三个参数分别放在 EAX、EDX、ECX,后面如果还有更多参数的话,就在堆栈里面;对于类的方法,EAX 固定用于存放类实例的地址,EDX、ECX 分别存放前两个参数,其余参数进栈。(这方面的具体资料,在哪里可以找到,是Delphi帮助吗?)
现在,虽然还是有点模糊,总算把程序跑通了!谢谢了。
 
多人接受答案了。
 
后退
顶部