欢迎访问 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日