(原创贴,转载请注名,谢谢 )
起源:
近日来,一直致力于扩充公司的脚本解析引擎!脚本引擎的大致扩充功能如下:
1、可在脚本中由用户自定义函数功能了,原来只有一个程序入口所有代码都在Begin..End之间写
Begin
//代码脚本
end
现在分成主脚本入口(既原Begin..End)与函数定义如
function GetMax(x,y: integer): integer;
begin
if x > y then
result := x
else
result := y;
end;
begin
MessageBox(GetMax(2,3));
end;
2、可支持在脚本中动态创建对象于对象之间传递引用
原引擎只能固定的使用一些对象,其间不可赋值与引用如
在Delphi中固定好一个对象 Button,则在脚本中使用就只能使用
Button.Caption := 'sdf';
而不支持 B := Button; 然后操作B;
现在扩充如:
MyBtn := TButton.Create(self);//支持了动态创建
MyBtn.caption := 'test';
MyBtn.parent := self;
CBtn := MyBtn;//支持了引用
MessageBox(CBtn.Caption);
3、可支持在脚本中使用编译预处理指令了如
{$I MyFuncLib} //引用外部库,相当于Include
{$IFDEF gg}
{$ELSEIFDEF bb}
{$ENDIF}
{$IFNDEF cc}
等编译预处理指令
现在问题就出现于第四点的实现方式上了!
那就是 动态的指定对象的事件了!
此时,由于事件的类型有很多种!如果一个个的定义下来处理的话,实在太过繁琐!所以想到使用一个函数来实现
调用所有对象事件的实现!而这些对象事件的的实现代码出现在脚本中,所以所有的事件执行都通过一个函数
DoEvent来实现,该函数中只处理某对象事件属性对应的函数脚本。那么就需要传递触发该事件的时候传递到事件中的
事件参数了!于是一个如何得到传递参数值的想法产生!
实践!
定义两个窗体,Form1,form2,在Form1中定义一个事件
TTestEvent = procedure(Sender: TObject;x,y,z: integer) of object;
property OnTest: TTestEvent read FonTest Write FOnTest;
然后在窗体创建的时候设定OnTest属性的值!
var
Method: TMethod;
begin
MeThod.Data := Sender;
Method.Code := @Test;
SetMethodProp(self,'OnTest',Method)
end;
Test过程没有任何参数,此时的目的就是要在Test中得到由触发该事件的时候传递过来的各个参数的值!
如
procedure Test;
begin
//这里要求得到参数值!
end;
一段触发该事件的代码如下:
Form1.OnTest(form1,1,2,3);
打个断点。运行到这里的时候打开CPU窗口得到如下代码:
{说明:对于一般的函数或过程,前三个参数分别放在 EAX、EDX、ECX,后面如果还有更多参数的话,就在堆栈
里面;对于类的方法,EAX 固定用于存放类实例的地址,EDX、ECX 分别存放前两个参数,其余参数进栈。在堆
栈中每个元素占用 4 Bytes,而前面说了,TVarRec 中储存的数据也是 4 Bytes,刚好一个参数在堆栈里面占
一个位子,处理方便。另外,结果返回到 EAX 中。
对于调用类的方法,其实有一个默认的隐藏参数 Self 作为第一个参数传入,放入EAX寄存器。
因此我们看到的第一参数其实是第二个,因此我们处理的时候要注意。}
Unit2.pas.36: Form1.OnTest(form1,1,2,3);
00461481 6A02 push $02 //这里可知道是第三个参数压栈,2
00461483 6A03 push $03 //第四个参数压栈,3
00461485 8B1DA83C4600 mov
关于函数调用得到传递参数的想法
最新推荐文章于 2023-04-30 14:23:07 发布
本文探讨了在脚本解析引擎中如何实现动态指定对象事件并传递参数的问题。作者通过实例展示了如何在Delphi中处理事件参数,包括利用EAX、EDX、ECX寄存器和堆栈来获取传递的参数值,并给出了一个处理事件参数的Test函数示例,展示了如何在事件处理函数内部获取和显示参数值。
摘要由CSDN通过智能技术生成