C/C++注册动态对象到Lu系统并进行运算符重载(五)

2014-11-24 07:38:58 · 作者: · 浏览: 1
or_o(m,Para,hFor); default: a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0; //没有重载该运算符或者函数,返回nil SetRunErr(1,LVector 无法识别的运算符!,theOperator,0,hFor); } return a; } void main(void) { void *hFor; //存放表达式句柄,即脚本函数句柄 luINT nPara; //存放表达式的自变量个数 LuData *pPara; //存放输入自变量的数组指针 luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置 int ErrCode; //错误代码 LuData Val; //Lu基本数据类型 void *v=NULL; //为了避免编译器报错,初始化为NULL luVOID k=0; //32位平台上luVOID被定义为__int32;64位平台上luVOID被定义为__int64;k必须赋值为0 wchar_t ForStr[]=Lmain(:a)= a=new[Vector], a.#x=1.1, a.#y=2.2, a.#z=3.3, o[a]; //字符串表达式 setlocale(LC_ALL, chs); //设置可以输出中文 if(!InitLu()) return; //初始化Lu Vector_x = StrToUniInt((char *)Lx,2); //由字符串x获得一个唯一的整数,用于标识Vector的成员x Vector_y = StrToUniInt((char *)Ly,2); //由字符串y获得一个唯一的整数,用于标识Vector的成员y Vector_z = StrToUniInt((char *)Lz,2); //由字符串z获得一个唯一的整数,用于标识Vector的成员z Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=key_Vector; //定义整数常量Vector,标识Vector对象 SetConst(LVector,&Val); //设置常量 SetFunction(Laddsub,Vector_addsub,3); //设置二级函数addsub,有4个参数 InsertKey((char *)&k,sizeof(luVOID),luPubKey_User,LuMessage,NULL,NULL,1,v);//使Lu运行时可输出函数信息 LockKey(key_Vector,Del_Vector,OpLock_Vector); //在Lu键树中加锁键,只能存储Vector类型 ErrCode=LuCom(ForStr,0,0,0,&hFor,&nPara,&pPara,&ErrBegin,&ErrEnd); //编译表达式 if(ErrCode) { printf(表达式有错误!错误代码: %d ,ErrCode); } else { LuCal(hFor,pPara); //运行表达式 } LockKey(key_Vector,NULL,OpLock_Vector); //在Lu键树中解锁键 FreeLu(); //释放Lu }


运行结果:

Vector x = 1.1, y = 2.2, z = 3.3

4 函数说明

本例用到了Lu的近一半的输出函数:初始化Lu的函数InitLu,释放Lu的函数FreeLu,编译表达式的函数LuCom、计算表达式的函数LuCal、加锁键函数LockKey、注册常量的函数SetConst、注册C/C++函数的函数SetFunction、由字符串获得一个唯一的整数StrToUniInt、插入键值的函数InsertKey、搜索键值的函数SearchKey、从缓冲区中获取一个对象的函数GetBufObj、从二级函数返回一个动态对象FunReObj、通过二级函数的参数返回多个动态对象FunSaveObj、设置运行错误的函数SetRunErr。从这里查看这些函数的说明:Lu编程指南。

5 难点分析

在给自定义动态类型数据添加运算符重载功能时,需要:(1)用LockKey加锁一个键(本例为key_Vector),自定义的动态类型数据使用该键向Lu系统进行注册,并注册为指针键,以便于Lu系统对垃圾对象的管理(若注册为非指针键,需要自己进行管理);(2)定义删除键值的函数(本例为Del_Vector);(3)定义运算符重载函数(本例为OpLock_Vector)。

在用C/C++进行Lu二级函数设计时,勿忘有关注意实现,参考函数SetFunction的说明。另外,为了提高运行效率,应优先使用函数GetBufObj从缓冲池获取一个动态对象。

代码中定义的Lu二级函数,只有Vector_addsub直接注册到了Lu系统,其余的函数Vector_mul、Vector_new、Vector_oset、Vector_oget、Vector_o是通过Vector对象的运算符重载或者函数重载来间接调用的。注意重载函数Vector_o设计时,o函数除了返回对象信息外,还要返回信息字符串的字符个数。

在Lu脚本中,对象成员一般用#开头的字符串标识,例如 #name 。本例对象Vector的的成员也使用这种表示方法,例如,设a是一个Vector对象,可实现赋值 a.#x=1.1, a.#y=2.2, a.#z=3.3 。实现原理很简单:Lu脚本编译器在编译字符串表达式时,如遇到以#开头的字符串(例如 #name),就使用该字符串生成一个在Lu脚本中唯一的整数(该整数在Lu系统运行期间保持不变),故本程序main函数一开始,就用函数StrToUniInt获取了相关字符串对应的整数值,用以标识Vector对象的成员。

(1)如果修改代码中的字符串表达式为(注意C/C++字符串中转义字符 的使用):

main(:a)= a=new[Vector], a.#x=1., a.#y=2., a.#z=3., o[a.#x, ,a.#y, ,a.#z, ]

可得到如下结果:

1. 2. 3.

(2)如果修改代码中的字符串表达式为:

main(:a,b)= a=new[Vector], a.#x=1., a.#y=2., a.#z=3., b=new[Vector], b.#x=7., b.#y=6., b.#z=5., o[a*b]

可得到如下结果:

Vector x = -8., y = 16., z = -8.

(3)如果修改代码中的字符串表达式为:

main(:a,b,c,d)= a=new[Vector], a.#x=1., a.#y=2., a.#z=3., b=new[Vector], b.#x=7., b.#y=6., b.#z=5., addsub[a,b,&c,&d], o[c,d]

可得到如下结果:

Vector x = 8., y = 8., z = 8. Vector x = -6., y = -4., z = -2.

(4)如果修改代码中的字符串表达式为(注意C/C++字符串中转义字符 的使用):

main(:a,b,i,t0)= t0=clock(), a=new[Vector], a.#x=1., a.#y=2., a.#z=3., b=new[Vector], b.#x=1., b.#y=0., b.#z=0., i=0, while{++i<=1000000, a=a*b}, o[a, time= ,clock()-t0, ms. ]

可得到如下结果: