欢迎访问 Lu程序设计
使用C/C++设计Lu脚本函数时调用Lu脚本函数
1 说明
要演示本文的例子,你必须下载Lu64脚本系统。本文的例子需要lu64.dll、lu64.lib、C格式的头文件lu64.h,相信你会找到并正确使用这几个文件。
用C/C++编译器创建一个控制台应用程序,复制本文的例子代码直接编译运行即可。
2 关于Lu表达式句柄(函数)的使用
在Lu脚本中,可以用编译符@获得表达式句柄(也称为表达式指针、函数指针、函数句柄)传给函数,或者使用函数HFor("ForName")获得表达式句柄,详细参考Lu用户指南。
本节讨论使用C/C++设计Lu二级函数时如何使用表达式句柄的问题。通常,与使用动态对象前要验证类似,在二级函数中使用表达式句柄时需要用函数GetFor验证,详细参考Lu编程指南。
3 代码
#include <stdio.h> #include "lu64.h" #pragma comment( lib, "lu64.lib" ) //Lu脚本可调用的二级函数定义 //arrayfor[@f,x]:用表达式句柄f对实数动态数组x做运算,返回一个新的动态数组 LuData _stdcall lu_arrayfor(luINT mm,LuData *xx,void *vFor) { static wchar_t ErrName[]=L"arrayfor"; void *pFor; luVOID nModule; luINT nPara; luRealArray *pReal0,*pReal; //Lu动态实数数组指针 luVOID i; LuData *pPara,a; a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0; if(!GetFor(NULL,0,(void *)*(luVOID *)&(xx->x),&nModule,&pFor,&pPara,&nPara)) //验证表达式 { SetRunErr(1,ErrName,1,0,vFor); return a; //指定的表达式不存在 } if(nPara!=0) //不是一元函数 { SetRunErr(1,ErrName,2,0,vFor); return a; } pReal=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray); //验证数组 if(!pReal) //不是动态实数数组 { SetRunErr(1,ErrName,3,0,vFor); return a; } pReal0=(luRealArray *)NewSysObj(luDynData_realarray,pReal->ArrayLen,pReal->DimLen); //申请系统内置动态数组 if(!pReal0) //内存错误 { SetRunErr(1,ErrName,4,0,vFor); return a; } for(i=0;i<pReal->DimLen;i++) //设置新数组的维数 { pReal0->Dim[i]=pReal->Dim[i]; } for(i=0;i<pReal->ArrayLen;i++) //复制数据到新数组 { pReal0->Array[i]=pReal->Array[i]; } for(i=0;i<pReal->ArrayLen;i++) //用表达式(函数)指针对数组矢量化运算 { pPara->BType=luStaData_double; pPara->VType=luStaData_double; *(double *)&(pPara->x)=pReal0->Array[i]; a=LuCal(pFor,pPara); //计算表达式的值 if(a.BType==luStaData_double) { pReal0->Array[i]=*(double *)&(a.x); } else //表达式返回值不是一个实数 { SetRunErr(1,ErrName,5,0,vFor); return a; } } a.BType=luDynData_realarray; a.VType=luDynData_realarray; *(luVOID *)&(a.x)=(luVOID)pReal0; FunReObj(vFor); //返回一个动态对象 return a; } void main(void) { void *hFor,*hMain; //表达式句柄 luINT nPara; //存放表达式的自变量个数 LuData *pPara; //存放输入自变量的数组指针 luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置 LuData Val; //Lu基本数据类型 luRealArray *pReal; //Lu动态实数数组指针 luVOID i,j; wchar_t ForStr[]=L"f(x)= x+1.0"; //字符串表达式 wchar_t MainStr[]=L"main(:a)= a=new[reals,2,3,data: 1.1,2.2,3.3,4.4,5.5,6.6], yield[arrayfor(@f,a)]";//字符串表达式 if(!InitLu()) return; //初始化Lu SetFunction(L"arrayfor",lu_arrayfor,1); //设置二级函数,有2个参数 if( LuCom(ForStr,0,0,0,&hFor,&nPara,&pPara,&ErrBegin,&ErrEnd) || //编译表达式 LuCom(MainStr,0,0,0,&hMain,&nPara,&pPara,&ErrBegin,&ErrEnd)) { printf("表达式有错误!"); } else { Val=LuCal(hMain,pPara); //计算MainStr表达式的值 pReal=(luRealArray *)SearchKey((char *)&(Val.x),sizeof(luVOID),luDynData_realarray); //验证数组 if(pReal) { if(pReal->DimLen==2) { for(i=0;i<pReal->Dim[0];i++) { for(j=0;j<pReal->Dim[1];j++) { printf("%f ",pReal->Array[i*pReal->Dim[1]+j]); } printf("\n"); } } } } FreeLu(); //释放Lu }
运行结果:
2.100000 3.200000 4.300000
5.400000 6.500000 7.600000
4 函数说明
本例用到了Lu的10个输出函数:初始化Lu的函数InitLu,释放Lu的函数FreeLu,编译表达式的函数LuCom、 计算表达式的函数LuCal、获得表达式信息函数GetFor、设置运行错误函数SetRunErr、申请系统内置动态对象函数NewSysObj、查找键值函数SearchKey、 二级函数返回一个动态对象FunReObj、C/C++向Lu注册二级函数SetFunction。从这里查看这些函数的说明:Lu编程指南。
5 难点分析
本例用C/C++设计了一个二级函数lu_arrayfor,用法如下:
arrayfor[@f,x]:用表达式句柄f对实数动态数组x做运算,返回一个新的动态数组。
该函数对运行错误详细进行了区分:1:无效的表达式句柄;2:表达式不是一个一元函数;3:不是动态实数数组;4:内存错误;5:表达式返回值不是一个实数。
注意函数lu_arrayfor中,不能将如下程序段:
for(i=0;i<pReal->ArrayLen;i++) //复制数据到新数组
{
pReal0->Array[i]=pReal->Array[i];
}
for(i=0;i<pReal->ArrayLen;i++) //用表达式(函数)指针对数组矢量化运算
{
pPara->BType=luStaData_double; pPara->VType=luStaData_double; *(double *)&(pPara->x)=pReal0->Array[i];
a=LuCal(pFor,pPara); //计算表达式的值
if(a.BType==luStaData_double)
{
pReal0->Array[i]=*(double *)&(a.x);
}
else //表达式返回值不是一个实数
{
SetRunErr(1,ErrName,5,0,vFor); return a;
}
}
改为:
for(i=0;i<pReal->ArrayLen;i++) //用表达式(函数)指针对数组矢量化运算
{
pPara->BType=luStaData_double; pPara->VType=luStaData_double; *(double *)&(pPara->x)=pReal->Array[i];
a=LuCal(pFor,pPara); //计算表达式的值
if(a.BType==luStaData_double)
{
pReal0->Array[i]=*(double *)&(a.x);
}
else //表达式返回值不是一个实数
{
SetRunErr(1,ErrName,5,0,vFor); return a;
}
}
原因是:Lu脚本允许用户用delete立即销毁一个动态对象,故执行LuCal(pFor,pPara)后,数组pReal可能被销毁。当然,除非脚本用户有意破坏,这种情况是极难遇到的;但对于C/C++用户来说,有责任努力保证任何情况下程序都不会崩溃。
另外,在字符串表达式MainStr中,使用yield返回了动态对象,或者使用global函数,如下所示:
main(:a)= a=new[reals,2,3,data: 1.1,2.2,3.3,4.4,5.5,6.6], global[arrayfor(@f,a)]
6 其他
你可能注意到了,我的联系方式就在下面,如有不明之处或有什么建议,可随时与我进行联系。
版权所有© Lu程序设计
2002-2021,保留所有权利
E-mail: forcal@sina.com
QQ:630715621
最近更新:
2021年05月23日