欢迎访问 Lu程序设计

使用C/C++设计多线程程序监控Lu脚本运行

1 说明

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

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

2 关于Lu无限循环的退出

    在Lu循环体(while或者until)中,必须有退出循环体的语句,否则将产生无限循环。例如 while[1,1] 就是一个无限循环。要想退出无限循环,必须设计成多线程程序,其中有一个线程专门用于监控Lu的运行,可以使用函数SetRunErr退出Lu无限循环,详细参考Lu编程指南

3 代码

#include <windows.h>
#include <iostream>
#include "lu64.h"

#pragma comment( lib, "lu64.lib" )

using namespace std;

DWORD idThread,lpExitcode;
HANDLE handleExitFc=NULL;
int ExitLu(void)
{
	MessageBox(NULL,L"强行退出Lu运行!",L"退出Lu!!!",32);
	SetRunErr(6,L"用户强行退出Lu!",1,0,0);
	return 0;
}

void main(void)
{
	void *hFor;			//表达式句柄
	luINT nPara;			//存放表达式的自变量个数
	LuData *pPara;			//存放输入自变量的数组指针
	luINT ErrBegin,ErrEnd;		//表达式编译出错的初始位置和结束位置
	int ErrCode;			//错误代码

	int ErrType,FunCode;		//返回运行错误或警告的类型,返回函数错误代码。
	wchar_t *FunName;			//返回出错函数名,或者运行错误说明。
	void *ForHandle;			//回出错表达式的句柄,该句柄即编译表达式时获得的句柄
	void *Msg1,*Msg2;			//与Lu交换信息用

	wchar_t divbyzeroStr[]=L"1/0";	//字符串表达式,编译时运行错误
	wchar_t recursionStr[]=L"a()=a()";	//字符串表达式,无穷递归调用
	wchar_t whileStr[]=L"while[1,1]";	//字符串表达式,无限循环

	wcout.imbue(locale("chs"));		//设置输出中文

	if(!InitLu()) return;		//初始化Lu

	ErrCode=LuCom(divbyzeroStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd);
	if(ErrCode)
	{
		wcout << L"表达式编译时出错!错误代码:" << ErrCode << endl;

		//检查Lu编译时运行错误
		GetRunErr(ErrType,FunName,FunCode,ForHandle);
		if(ErrType)
		{
			wcout << L"Lu运行错误,错误类型:" << ErrType << L"  函数名: " << FunName << L" 错误代码:" << FunCode << endl;
			if(ForHandle)
			{
				FunName=(wchar_t *)ExMsgWithLu(2,ForHandle,Msg1,Msg2);
				wcout << L"表达式名称:" << FunName << L" 所在模块:" << *(luVOID *)Msg1 << endl;
			}
		}

	}

	if(0==LuCom(recursionStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd))
	{
		LuCal(hFor,pPara);		//执行表达式

		//检查Lu运行错误
		GetRunErr(ErrType,FunName,FunCode,ForHandle);
		if(ErrType)
		{
			wcout << endl << L"Lu运行错误,错误类型:" << ErrType << L"  函数名: " << FunName << L" 错误代码:" << FunCode << endl;
			if(ForHandle)
			{
				FunName=(wchar_t *)ExMsgWithLu(2,ForHandle,Msg1,Msg2);
				wcout << L"表达式名称:" << FunName << L" 所在模块:" << *(luVOID *)Msg1 << endl;
			}
		}

	}

	//创建一个线程,监控Lu运行
	handleExitFc=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ExitLu,NULL,0,&idThread);

	if(0==LuCom(whileStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd))
	{
		LuCal(hFor,pPara);		//执行表达式

		//检查Lu运行错误
		GetRunErr(ErrType,FunName,FunCode,ForHandle);
		if(ErrType)
		{
			wcout << endl << L"Lu运行错误,错误类型:" << ErrType << L"  函数名: " << FunName << L" 错误代码:" << FunCode << endl;
			if(ForHandle)
			{
				FunName=(wchar_t *)ExMsgWithLu(2,ForHandle,Msg1,Msg2);
				wcout << L"表达式名称:" << FunName << L" 所在模块:" << *(luVOID *)Msg1 << endl;
			}
		}
	}

	FreeLu();		//释放Lu
}

运行结果:

表达式编译时出错!错误代码:36
Lu运行错误,错误类型:1 函数名: Integer division by zero 错误代码:1

Lu运行错误,错误类型:1 函数名: StackOverFlow 错误代码:1
表达式名称:a 所在模块:0

Lu运行错误,错误类型:6 函数名: 用户强行退出Lu! 错误代码:1

4 函数说明

    本例用到了Lu的7个输出函数:初始化Lu的函数InitLu,释放Lu的函数FreeLu,编译表达式的函数LuCom、 计算表达式的函数LuCal、设置运行错误函数SetRunErr、 获得运行错误函数GetRunErr、与Lu交换信息函数ExMsgWithLu。从这里查看这些函数的说明:Lu编程指南

5 难点分析

    Lu在编译字符串表达式时,对常量表达式(例如 1/2)会进行计算,因而有可能返回运行错误,编译错误代码36表示出现了运行错误,此时应检查并报告运行错误。

    Lu在计算表达式时,极有可能出现运行错误,故应对运行错误进行检查。如果运行多个表达式,不必在每个表达式运行后进行检查,可在最后检查运行错误。

6 其他

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


版权所有© Lu程序设计 2002-2021,保留所有权利
E-mail: forcal@sina.com
  QQ:630715621
最近更新: 2021年05月23日