C/C++注册动态对象到Lu系统并进行运算符重载
1 说明
要演示本文的例子,你必须下载Lu32脚本系统。本文的例子需要lu32.dll、lu32.lib、C格式的头文件lu32.h,相信你会找到并正确使用这几个文件。
用C/C++编译器创建一个控制台应用程序,复制本文的例子代码直接编译运行即可。
2 关于运算符重载
在本教程系列的开始,介绍了Lu脚本的基本数据结构(详细参考Lu编程指南),即:
struct LuData{ //Lu基本数据结构。
luIFOR x; //luIFOR被定义为64位整数__int64,用于存放数据。对于动态数据类型,对象指针约定保存在x的前4个字节中。
luIFOR y; //存放数据。
luIFOR z; //存放数据。
luKEY VType; //luKEY被定义为32位整数__int32。扩展数据类型,决定重载函数,从而决定了对数据的操作方式。
luKEY BType; //基本数据类型,决定了Lu数据的结构。
};
基本数据类型BType决定了实际的数据结构,而扩展数据类型VType决定了重载函数。若要对某数据类型VType进行运算符重载,需要用函数LockKey对VType加锁,该函数定义如下:
int _stdcall LockKey(luKEY VType,void (_stdcall *DeleteKey)(void *),luOperator OpLock);
VType:被锁定的键的类型。VType>luPubKey_User(公有键、普通键)或者 VType
OpLock:luOperator类型的函数指针,用于对象(用指针标识)的运算符重载,该参数不可为NULL。解锁和加锁所用的OpLock函数必须相同。参考
[注1]。
如果加锁或解锁成功,该函数返回0,否则返回非0值。
[注1]:运算符重载函数luOperator函数格式如下(与Lu二级函数相比,仅多了一个参数theOperator):
//m指出数组Para的参数个数(也即操作数的个数,0表示1个,1表示2个,以此类推)。
//hFor为调用该函数的表达式句柄(与二级函数中的表达式句柄相同)。
//theOperator指出运算符的类型或操作类型:+、-、*、/、^、... ...。
LuData (_stdcall *luOperator)(luINT m,LuData *Para,void *hFor,int theOperator);
LuData _stdcall OpLock(luINT m,LuData *Para,void *hFor,int theOperator)
{
//... ...
switch(theOperator)
{
case 0: //重载运算符+
//... ...
case 1: //重载运算符-
//... ...
case 2: //重载运算符*
//... ...
case 3: //重载运算符%
//... ...
case 4: //重载运算符/
//... ...
... ...
}
}
如果不打算给加锁的键提供运算符或函数重载功能,须使用函数SetRunErr向Lu报告运行错误。
本文讨论C/C++注册动态对象到Lu系统并进行运算符重载。本文的例子是实现三维向量及部分相关运算(基本类型和扩展类型均为 key_Vector)。实际上,Lu脚本中内置了三维向量(vector)的运算,例如:
(1$2$3) * (7$6$5)
结果为:
(-8.,16.,-8.)
Lu脚本内置的三维向量(vector)是静态数据,但本文的三维向量(Vector)被定义为动态数据,仅为了演示如何将动态对象注册到Lu系统并进行运算符重载。同时,本文还演示了二级函数如何返回一个动态对象;演示了二级函数如何通过参数返回多个动态对象;演示了重载函数new、oset、oget、o的用法;演示了如何由字符串获得一个唯一的整数,以及该整数在Lu脚本中的用法;演示了如何在Lu系统中注册常量和函数;演示了如何接收Lu系统的字符串信息等等。
由于演示的项目较多,本文的例子代码较长。
3 代码
#include#include #include #include #include lu32.h #pragma comment( lib, lu32.lib ) luKEY key_Vector = luPriKey_User-20; //标识Vector对象的私有键,将对其加锁 //在Lu脚本中,对象成员一般用#开头的字符串标识,例如 #name luVOID Vector_x; //标识Vector的成员x,在Lu脚本中,设a是一个Vector,则成员x的表示为 a.#x luVOID Vector_y; //标识Vector的成员y,在Lu脚本中,设a是一个Vector,则成员y的表示为 a.#y luVOID Vector_z; //标识Vector的成员z,在Lu脚本中,设a是一个Vector,则成员z的表示为 a.#z typedef struct lu_Vector //Vector结构定义,将注册为私有键 { double x; double y; double z; } lu_Vector; void _stdcall Del_Vector(void *me) //销毁Vector的函数,将注册到Lu系统,实现自动销毁Vector对象 { free(me); } void _stdcall LuMessage(wchar_t *pch) //输出动态库信息,该函数注册到Lu,由Lu二级函数调用 { wprintf(L%s,pch); } //定义Lu脚本可调用的二级函数 //演示二级函数如何返回一个动态对象,通过运算符*重载调用 LuData _stdcall Vector_mul(luINT mm,LuData *xx,void *vFor) //计算两个Vector的积,返回一个新Vector { static wchar_t ErrName[]=LVector *; lu_Vector *pVector0,*pVector1,*pVector2; void *NowKey=NULL; //为避免编译器发出警告进行初始化,实际上不需要 char keyname[sizeof(luVOID)]; LuData a; if(xx->BType==key_Vector && (xx+1)->BType==key_Vector) { pVector1=(lu_Vector *)SearchKey((char *)&(xx[0].x), sizeof(luVOID), key_Vector); pVector2=(lu_Vector *)SearchKey((char *)&(xx[1].x), sizeof(luVOID), key_Vector); if(!pVector1 || !pVector2) goto err; pVector0=(lu_Vector *)GetBufObj(key_Vector,keyname); //先尝试从缓冲区中获取一个Vector对象 if(!pVector0) { pVector0=(lu_Vector *)malloc(sizeof(lu_Vec