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

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

yanfei0891_firs

Unregistered / Unconfirmed
GUEST, unregistred user!
http://www.tommstudio.com/newclub30/d_displayjqxw.asp<br><br><br>怎样按名字调用某个类的方法?(在 不知道方法的参数个数及类型 的条件下)<br>这篇文章 http://www.tommstudio.com/newclub30/d_displayjqxw.asp 提供了<br>一种方法可以调用,但当方法的参数有real,或者currency型时 传入的参数值<br>就不对了,大家知道是为什么吗?<br>具体的程序如下:<br>调用的方法:<br>function ExecuteRoutine(AObj: TObject; AName: string;<br>&nbsp; &nbsp; Params: array of const): DWord;<br>&nbsp; const<br>&nbsp; &nbsp; RecSize = SizeOf(TVarRec); // 循环处理参数列表时递增的字节数<br>&nbsp; var<br>&nbsp; &nbsp; PFunc: Pointer;<br>&nbsp; &nbsp; ParCount: DWord;<br>&nbsp; begin<br>&nbsp; &nbsp; if not Assigned(AObj) then<br>&nbsp; &nbsp; &nbsp; raise Exception.Create ('你确定传进来的是一个对象?');<br>&nbsp; &nbsp; PFunc := AObj.MethodAddress(AName); // 获取方法地址<br>&nbsp; &nbsp; if not Assigned(PFunc) then<br>&nbsp; &nbsp; &nbsp; raise Exception.CreateFmt('找不到 %s 的 Method: %s', [AObj.ClassName,<br>&nbsp; &nbsp; &nbsp; &nbsp; AName]);<br>&nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; ParCount := High(Params) + 1; // 获取参数个数<br><br>&nbsp; &nbsp; asm<br>&nbsp; &nbsp; &nbsp; PUSH &nbsp; &nbsp; &nbsp; &nbsp;ESI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 保存 ESI,我们待会儿要用到它<br><br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;ESI, Params &nbsp; &nbsp; &nbsp; &nbsp;// ESI 指向参数表首址<br>&nbsp; &nbsp; &nbsp; CMP &nbsp; &nbsp; &nbsp; &nbsp;ParCount, 1 &nbsp; &nbsp; &nbsp; &nbsp;// 判断参数个数<br>&nbsp; &nbsp; &nbsp; JB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@NoParam<br>&nbsp; &nbsp; &nbsp; JE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@OneParam<br>&nbsp; &nbsp; &nbsp; CMP &nbsp; &nbsp; &nbsp; &nbsp;ParCount, 2<br>&nbsp; &nbsp; &nbsp; JE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@TwoParams<br><br>&nbsp; &nbsp; @ManyParams: // 超过两个参数<br>&nbsp; &nbsp; &nbsp; CLD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 清空方向标志<br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;ECX, ParCount<br>&nbsp; &nbsp; &nbsp; SUB &nbsp; &nbsp; &nbsp; &nbsp;ECX, 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 循环 ParCount - 2 次<br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;EDX, RecSize &nbsp; &nbsp; &nbsp; &nbsp;// EDX 依次指向每个参数的首址,每次递增 8 Bytes<br>&nbsp; &nbsp; &nbsp; ADD &nbsp; &nbsp; &nbsp; &nbsp;EDX, RecSize &nbsp; &nbsp; &nbsp; &nbsp;// 跳过前两个参数<br>&nbsp; &nbsp; @ParamLoop:<br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;EAX, [ESI][EDX] &nbsp; &nbsp;// 用基址变址寻址方式取得一个参数<br>&nbsp; &nbsp; &nbsp; PUSH &nbsp; &nbsp; &nbsp; &nbsp;EAX &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 参数进栈<br>&nbsp; &nbsp; &nbsp; ADD &nbsp; &nbsp; &nbsp; &nbsp;EDX, RecSize &nbsp; &nbsp; &nbsp; &nbsp;// EDX 指向下一个参数首址<br>&nbsp; &nbsp; &nbsp; LOOP &nbsp; &nbsp; &nbsp; &nbsp;@ParamLoop<br><br>&nbsp; &nbsp; @TwoParams: // 两个参数<br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;ECX, [ESI] + RecSize<br><br>&nbsp; &nbsp; @OneParam: // 一个参数<br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;EDX, [ESI]<br><br>&nbsp; &nbsp; @NoParam:<br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;EAX, AObj &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 传入实例地址(即,隐藏参数 Self)<br>&nbsp; &nbsp; &nbsp; CALL &nbsp; &nbsp; &nbsp; &nbsp;PFunc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 调用方法<br>&nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; &nbsp; &nbsp;Result, EAX &nbsp; &nbsp; &nbsp; &nbsp;// 返回值放入 Result<br><br>&nbsp; &nbsp; &nbsp; POP &nbsp; &nbsp; &nbsp; &nbsp;ESI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 记得还原<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>被调用的方法<br>procedure TForm1.avg(Const a,b : Currency;var c : Currency);<br>begin<br>&nbsp; c := &nbsp;(a + b)/2 ;<br>end;<br>调用:<br>&nbsp;begin<br>&nbsp;var j : Currency;<br>&nbsp;ExecuteRoutine(Form1,'avg',[12.21,12.32,@j]);<br>&nbsp;end;<br>调用时跟踪 a,b的值都不对了,但如果 a,b设成integer型就可以了
 
不好意思,问题我已经解决了<br>就是把avg过程的参数a,b去掉const定义<br>因为本来ExecuteRoutine这个函数的功能就是传入 指针<br>在avg方法中把参数定义为const当然不行<br>但又出来一个问题,如果我确实要把a,b定义成Const,那该怎么办呢?
 
后退
顶部