使用C/C++设计Lu脚本函数时调用Lu脚本函数

使用C/C++设计Lu脚本函数时调用Lu脚本函数

1 说明

    要演示本文的例子,你必须下载Lu32脚本系统。本文的例子需要lu32.dll、lu32.lib、C格式的头文件lu32.h,相信你会找到并正确使用这几个文件。

    用C/C++编译器创建一个控制台应用程序,复制本文的例子代码直接编译运行即可。

2 关于Lu表达式句柄(函数)的使用

    在Lu脚本中,可以用编译符@获得表达式句柄(也称为表达式指针、函数指针、函数句柄)传给函数,或者使用函数HFor(“ForName”)获得表达式句柄,详细参考Lu用户指南。

    本节讨论使用C/C++设计Lu二级函数时如何使用表达式句柄的问题。通常,与使用动态对象前要验证类似,在二级函数中使用表达式句柄时需要用函数GetFor验证,详细参考Lu编程指南。

3 代码

[cpp] view plaincopy

  1. #include <stdio.h>
  2. #include “lu32.h”
  3. #pragma comment( lib, “lu32.lib” )
  4. //Lu脚本可调用的二级函数定义
  5. //arrayfor[@f,x]:用表达式句柄f对实数动态数组x做运算,返回一个新的动态数组
  6. LuData _stdcall lu_arrayfor(luINT mm,LuData *xx,void *vFor)
  7. {
  8.     static wchar_t ErrName[]=L”arrayfor”;
  9.     void *pFor;
  10.     luVOID nModule;
  11.     luINT nPara;
  12.     luRealArray *pReal0,*pReal; //Lu动态实数数组指针
  13.     luVOID i;
  14.     LuData *pPara,a;
  15.     a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
  16.     if(!GetFor(NULL,0,(void *)*(luVOID *)&(xx->x),&nModule,&pFor,&pPara,&nPara)) //验证表达式
  17.     {
  18.         SetRunErr(1,ErrName,1,0,vFor); return a; //指定的表达式不存在
  19.     }
  20.     if(nPara!=0)    //不是一元函数
  21.     {
  22.         SetRunErr(1,ErrName,2,0,vFor); return a;
  23.     }
  24.     pReal=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray); //验证数组
  25.     if(!pReal)  //不是动态实数数组
  26.     {
  27.         SetRunErr(1,ErrName,3,0,vFor); return a;
  28.     }
  29.     pReal0=(luRealArray *)NewSysObj(luDynData_realarray,pReal->ArrayLen,pReal->DimLen);   //申请系统内置动态数组
  30.     if(!pReal0) //内存错误
  31.     {
  32.         SetRunErr(1,ErrName,4,0,vFor); return a;
  33.     }
  34.     for(i=0;i<pReal->DimLen;i++)  //设置新数组的维数
  35.     {
  36.         pReal0->Dim[i]=pReal->Dim[i];
  37.     }
  38.     for(i=0;i<pReal->ArrayLen;i++)    //复制数据到新数组
  39.     {
  40.         pReal0->Array[i]=pReal->Array[i];
  41.     }
  42.     for(i=0;i<pReal->ArrayLen;i++)    //用表达式(函数)指针对数组矢量化运算
  43.     {
  44.         pPara->BType=luStaData_double; pPara->VType=luStaData_double; *(double *)&(pPara->x)=pReal0->Array[i];
  45.         a=LuCal(pFor,pPara);    //计算表达式的值
  46.         if(a.BType==luStaData_double)
  47.         {
  48.             pReal0->Array[i]=*(double *)&(a.x);
  49.         }
  50.         else    //表达式返回值不是一个实数
  51.         {
  52.             SetRunErr(1,ErrName,5,0,vFor); return a;
  53.         }
  54.     }
  55.     a.BType=luDynData_realarray; a.VType=luDynData_realarray; *(luVOID *)&(a.x)=(luVOID)pReal0;
  56.     FunReObj(vFor); //返回一个动态对象
  57.     return a;
  58. }
  59. void main(void)
  60. {
  61.     void *hFor,*hMain;      //表达式句柄
  62.     luINT nPara;        //存放表达式的自变量个数
  63.     LuData *pPara;      //存放输入自变量的数组指针
  64.     luINT ErrBegin,ErrEnd;  //表达式编译出错的初始位置和结束位置
  65.     LuData Val;     //Lu基本数据类型
  66.     luRealArray *pReal; //Lu动态实数数组指针
  67.     luVOID i,j;
  68.     wchar_t ForStr[]=L”f(x)= x+1.0″;    //字符串表达式
  69.     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)]”;//字符串表达式
  70.     if(!InitLu()) return;   //初始化Lu
  71.     SetFunction(L”arrayfor”,lu_arrayfor,1); //设置二级函数,有2个参数
  72.     if( LuCom(ForStr,0,0,0,&hFor,&nPara,&pPara,&ErrBegin,&ErrEnd) ||    //编译表达式
  73.         LuCom(MainStr,0,0,0,&hMain,&nPara,&pPara,&ErrBegin,&ErrEnd))
  74.     {
  75.         printf(“表达式有错误!”);
  76.     }
  77.     else
  78.     {
  79.         Val=LuCal(hMain,pPara); //计算MainStr表达式的值
  80.         pReal=(luRealArray *)SearchKey((char *)&(Val.x),sizeof(luVOID),luDynData_realarray);    //验证数组
  81.         if(pReal)
  82.         {
  83.             if(pReal->DimLen==2)
  84.             {
  85.                 for(i=0;i<pReal->Dim[0];i++)
  86.                 {
  87.                     for(j=0;j<pReal->Dim[1];j++)
  88.                     {
  89.                         printf(“%f  “,pReal->Array[i*pReal->Dim[1]+j]);
  90.                     }
  91.                     printf(“\n”);
  92.                 }
  93.             }
  94.         }
  95.     }
  96.     FreeLu();       //释放Lu
  97. }

运行结果:

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编程指南。

难点分析

本例用C/C++设计了一个二级函数lu_arrayfor,用法如下:

arrayfor[@f,x]:用表达式句柄f对实数动态数组x做运算,返回一个新的动态数组。

该函数对运行错误详细进行了区分:1:无效的表达式句柄;2:表达式不是一个一元函数;3:不是动态实数数组;4:内存错误;5:表达式返回值不是一个实数。

注意函数lu_arrayfor中,不能将如下程序段:

[cpp] view plaincopy

  1. for(i=0;i<pReal->ArrayLen;i++) //复制数据到新数组
  2. {
  3.     pReal0->Array[i]=pReal->Array[i];
  4. }
  5. for(i=0;i<pReal->ArrayLen;i++) //用表达式(函数)指针对数组矢量化运算
  6. {
  7.     pPara->BType=luStaData_double; pPara->VType=luStaData_double; *(double *)&(pPara->x)=pReal0->Array[i];
  8.     a=LuCal(pFor,pPara); //计算表达式的值
  9.     if(a.BType==luStaData_double)
  10.     {
  11.         pReal0->Array[i]=*(double *)&(a.x);
  12.     }
  13.     else //表达式返回值不是一个实数
  14.     {
  15.         SetRunErr(1,ErrName,5,0,vFor); return a;
  16.     }
  17. }

改为:

[cpp] view plaincopy

  1. for(i=0;i<pReal->ArrayLen;i++) //用表达式(函数)指针对数组矢量化运算
  2. {
  3.     pPara->BType=luStaData_double; pPara->VType=luStaData_double; *(double *)&(pPara->x)=pReal->Array[i];
  4.     a=LuCal(pFor,pPara); //计算表达式的值
  5.     if(a.BType==luStaData_double)
  6.     {
  7.         pReal0->Array[i]=*(double *)&(a.x);
  8.     }
  9.     else //表达式返回值不是一个实数
  10.     {
  11.         SetRunErr(1,ErrName,5,0,vFor); return a;
  12.     }
  13. }

原因是: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 其他

    你可能注意到了,我的联系方式就在下面,如有不明之处或有什么建议,可随时与我进行联系。

标签