怎样按名字调用某个类的方法?(在 不知道方法的参数个数及类型 的条件下)(50分)

  • 主题发起人 主题发起人 yanfei0891_firs
  • 开始时间 开始时间
Y

yanfei0891_firs

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样按名字调用某个类的方法?(在 不知道方法的参数个数及类型 的条件下)
这篇文章 http://www.tommstudio.com/newclub30/d_displayjqxw.asp 提供了
一种方法可以调用,但当方法的参数有real,或者currency型时 传入的参数值
就不对了,大家知道是为什么吗?
具体的程序如下:
调用的方法:
function ExecuteRoutine(AObj: TObject; AName: string;
Params: array of const): DWord;
const
RecSize = SizeOf(TVarRec); // 循环处理参数列表时递增的字节数
var
PFunc: Pointer;
ParCount: DWord;
begin
if not Assigned(AObj) then
raise Exception.Create ('你确定传进来的是一个对象?');
PFunc := AObj.MethodAddress(AName); // 获取方法地址
if not Assigned(PFunc) then
raise Exception.CreateFmt('找不到 %s 的 Method: %s', [AObj.ClassName,
AName]);

ParCount := High(Params) + 1; // 获取参数个数

asm
PUSH ESI // 保存 ESI,我们待会儿要用到它

MOV ESI, Params // ESI 指向参数表首址
CMP ParCount, 1 // 判断参数个数
JB @NoParam
JE @OneParam
CMP ParCount, 2
JE @TwoParams

@ManyParams: // 超过两个参数
CLD // 清空方向标志
MOV ECX, ParCount
SUB ECX, 2 // 循环 ParCount - 2 次
MOV EDX, RecSize // EDX 依次指向每个参数的首址,每次递增 8 Bytes
ADD EDX, RecSize // 跳过前两个参数
@ParamLoop:
MOV EAX, [ESI][EDX] // 用基址变址寻址方式取得一个参数
PUSH EAX // 参数进栈
ADD EDX, RecSize // EDX 指向下一个参数首址
LOOP @ParamLoop

@TwoParams: // 两个参数
MOV ECX, [ESI] + RecSize

@OneParam: // 一个参数
MOV EDX, [ESI]

@NoParam:
MOV EAX, AObj // 传入实例地址(即,隐藏参数 Self)
CALL PFunc // 调用方法
MOV Result, EAX // 返回值放入 Result

POP ESI // 记得还原
end;
end;
被调用的方法
procedure TForm1.avg(Const a,b : Currency;var c : Currency);
begin
c := (a + b)/2 ;
end;
调用:
begin
var j : Currency;
ExecuteRoutine(Form1,'avg',[12.21,12.32,@j]);
end;
调用时跟踪 a,b的值都不对了,但如果 a,b设成integer型就可以了
 
不好意思,问题我已经解决了
就是把avg过程的参数a,b去掉const定义
因为本来ExecuteRoutine这个函数的功能就是传入 指针
在avg方法中把参数定义为const当然不行
但又出来一个问题,如果我确实要把a,b定义成Const,那该怎么办呢?
 
后退
顶部