MLu32.dll V1.0 使用说明

 

欢迎访问Lu程序设计

MLu32.dll V1.0 使用说明

目  录

MLu说明

基于MLu的Lu扩展动态

1 MLu的输出函数
2 如何使用
MLu
3 二级函数
4 模块源文件
5 例子
1 OpenLuGl:基于OpenGL的图形库
2 LuWin:基于Windows的窗口库

    MLu是程序和Lu核心库之间的一个接口库,MLu会自动加载Lu核心库和动态加载多个Lu扩展库,简化了Lu系统的使用;MLu可对Lu源程序进行模块化编译,能够编译运行具有固定格式的源程序(字符串表达式),源程序中可以使用C++风格的注释。此外,MLu还提供了多个线程互斥地访问Lu资源的功能;提供了Lu运行监视器,以退出耗时较长的程序;提供在脚本中动态编译函数的功能;提供错误处理函数,实现错误(异常)处理的恢复模型等等。


1 MLu的输出函数  [目录]

    MLu共有10个输出函数,其中4个函数可在Lu键树中用SearchKey查询到,即:SearchKey("UseLu",5,luPriKey_User)SearchKey("ComModule",9,luPriKey_User)、SearchKey("ExeModule",9,luPriKey_User)SearchKey("DelModule",9,luPriKey_User)。这4个函数可用于Lu扩展库的设计。

1.1 初始化MLuint _stdcallInitMLu(void);

    MLu初始化后才能使用。该函数对MLu进行初始化,成功时返回非0值,返回0表示初始化失败。可使用该函数对MLu重新初始化,但必须关闭主程序中正在运行的Lu程序。

1.2 释放MLuvoid _stdcallFreeMLu(void);

    在使用完MLu之后必须用该函数释放加载的资源。

1.3 得到Lu核心库的句柄HINSTANCE _stdcallGetLuHandle(void);

    MLu会自动加载Lu核心库,该函数用于获得Lu核心库的句柄。

    警告:不要使用Lu核心库的InitLuFreeLu两个函数。

1.4 得到Lu核心库的输出函数void * _stdcallGetLuProc(char *name);

    name是Lu核心库的输出函数名。

    警告:不要使用Lu核心库的InitLuFreeLu两个函数。

1.5 加载Lu扩展动态库:void _stdcallLoadDll(wchar_t *DllStr);

    DllStr:含有Lu扩展动态库名称的字符串。

    允许加载多个Lu扩展动态库。Lu扩展动态库名字要放在双引号"..."之间。忽略在尖括号<"..." ...>内的Lu扩展动态库。

    例如:"LuMath32","d:\\lu\\LuSystem32.dll"

    需要注意Lu扩展动态库的加载顺序。

1.6 释放Lu扩展动态库:void _stdcallFreeDll(void);

1.7 申请进入或退出Lu工作区int _stdcallUseLu(int iUse);

    iUse=1时,表示要申请使用Lu,若函数返回值 UseLu=0:申请成功;UseLu=1:申请不成功,某线程正在使用Lu,稍后再进行申请;UseLu=-1:申请不成功,表示应用程序要释放Lu,因此要做好退出前的准备工作。
   
iUse=2时,表示要申请使用Lu,如果其他线程正在使用Lu,函数不返回,进行等待,直至申请成功。若函数返回值 UseLu=0:申请成功;UseLu=1:申请不成功,线程本身正在使用Lu,不能重复进行申请;UseLu=-1:申请不成功,表示应用程序要释放Lu,因此要做好退出前的准备工作。
   
iUse=0时,表示要归还Lu的使用权,函数返回值无意义。 
    iUse=3时,设置安全标志,表示Lu运行正常,函数返回值无意义。 一般在二级函数中设置该标志,当该函数在较长时间内运行时,可用此标志通知Lu,此时的运行是正常的,没有陷入无限循环等情况。
    iUse=4时,取消安全标志,表示Lu运行处于不可控制阶段(有陷入无限循环的可能),函数返回值无意义。 
    iUse=5时,查询安全标志,UseLu=0:运行正常;UseLu=1:运行情况无法预测(有陷入无限循环的可能),这是Lu运行的一般情况。 
   
注意:Lu是极为重要而有限的资源,用完后要及时归还。UseLu(1)(或者UseLu(2))和UseLu(0)必须成对使用,注意不能在二级函数中使用该功能,因为二级函数本身就是在Lu工作区中运行的。UseLu(3)UseLu(4)也要成对使用,且一般在二级函数中使用。
    可以在主调程序或Lu扩展动态库中使用该函数。在多线程程序中,必须通过申请Lu工作区的方法来使用Lu,因为在任何时刻,只允许一个线程使用Lu(GetRunErr()、TestRunErr()和SetRunErr()三个函数除外)。

1.8 编译源程序:int _stdcallComModule(wchar_t *LuStr,luVOID &nModule,void *&hModule,luINT &err1,luINT &err2);

    LuStr:指向源程序字符串的指针;
    nModule:返回多个模块的最小模块号。一般返回主模块号,如果主模块中没有表达式,就返回有表达式的最小子模块号。
    hModule:返回模块的句柄,用于执行该模块。
    err1和err2:返回编译出错位置,该值是否有意义取决于函数的返回值(返回值为-1、0、1、3、-2时无意义)。

    该函数返回值的意义如下:

    -7:递归调用指定的模块。(参考函数mluLoadModule的说明)
    -6:找不到指定的模块。(参考函数mluLoadModule的说明)
    -5:缺少模块名。
(由程序员处理,不返回给用户)
    -4:注释符号/* ... */不成对。
    -3:未使用模块编译功能,不能编译指定的模块。
    -2:无法加锁模块。
(由程序员处理,修改nModule为较小的值可能修正此错误)
    -1:未用!
    0:没有错误,编译成功!
    1:内存分配失败!
    2:括号不成对!
    3:(等号后)没有表达式!
    4:非法的函数句柄!
    5:字符串中转义字符错误!
    6:字符串无效,即"..."不匹配!
    7:不可识别字符!
    8:表达式名称定义错误!
    9:不可识别的自变量,自变量只能以字母、中文字符或下画线开头!
    10:不可识别的自变量定义方法,“(,:,:,:,:,...)”冒号过多!
    11:自变量定义错误!
    12:continue()函数只能有0个参数!
    13:只能在while,until中使用continue函数!
    14:break()函数只能有0个参数!
    15:只能在while,until中使用break函数!
    16:if,while,until,which中的参数个数至少为2个!
    17:表达式中的数字错误!
    18:&单目取地址运算符只能用于单独的变量!
    19:单目运算符++、--错误!
    20:括号内没有数字!
    21:单目运算符+、-、!、!!错误!
    22:赋值“=”错误!
    23:不正确的运算方式或其他语法错误!
    24:不可识别变量名或常量名!
    25:不可识别函数名!
    26:一级函数参数不匹配!
    27:二级函数参数不匹配!
    28:关键字Static或Common的位置非法!
    29:(模块中)表达式有重名!
    30:对形如“-2^3”的式子,须用括号给前置单目运算符“-”和乘方运算符“^”(或点乘方运算符“.^”)指出运算顺序!
    31:类成员运算符(函数参数运算符)后只能是变量名、字符串、括号运算符或者类成员函数!
    32:后单目运算符'、.'错误!
    33:调用表达式时参数不匹配!
    34:未用!
    35:自变量重名!
    36:因检测到运行错误而退出!
    37:未用!
    38:未用!
    39:源代码太长或字符串太多!

    编译时,将源程序中的表达式编译为一个或多个模块,MLu会对每一个模块进行加锁。编译时首先设置起始模块,也称主模块(并非Lu的0#模块,恰恰相反,MLu不会将任何一个表达式编译为0#模块,定义主模块是为了与源程序中的其他模块相区别),以后每当遇到#MODULE#,开始编译为一个新的模块,称为子模块,而每当遇到#END#,回到主模块的编译。即#MODULE##END#之间的表达式定义为一个子模块,子模块之间不能嵌套定义。注意#MODULE##END#必须位于表达式的开头。

    当nModule为0时,所有模块的模块号自动指定(MLu初始化时,设置最初的起始模块号为1,以后不断递增,但不一定连续,因为每次执行该函数,不管是否执行成功,模块号均加1),不会重复,也不会被编译为0#模块。任何时候,可用nModule传送给MLu一个起始模块号(必须大于0),以后的模块号将在该模块号的基础上递增,从而改变模块号序列。若要自己指定模块号,则每次编译源程序前,均指定一个起始模块号。MLu编译的多个模块序号是递增的,但不一定连续,因为如果MLu加锁一个模块不成功,就会继续加锁下一个模块号。

    在模块中,以:::开头的表达式被编译为正模块号表达式(公有表达式或公有函数,也称为全局函数),能被其他模块访问到,其余的表达式均被编译为负模块号表达式(私有表达式或私有函数),其他模块无法访问。

    在源程序的任何地方,可用指令#USE#调用另一个模块。

    模块源文件的格式如下(没有定义子模块,子模块的例子请参考这里):

      //单行注释:模块名:myModule
      /*
        多行注释:在同一模块源文件中的所有表达式属于同一个模块;
        多行注释:以:::开头的表达式的模块号为正,可被其他模块的表达式所访问;
        多行注释:不以:::开头的表达式的模块号为负,只能被该模块的表达式所访问。
      */
      a(x)=10+x;          //模块号为负,私有函数,只能被该模块的表达式所访问;
      b()=100+100i;       //模块号为负,私有函数,只能被该模块的表达式所访问;
      :::c(x)=x-5;        //模块号为正,全局函数,任意模块包括本模块均可访问; 
      :::f(x)=a(x)+b();   //模块号为正,全局函数,任意模块包括本模块均可访问; 
      :::g(x)=a(x)+c(x);  //模块号为正,全局函数,任意模块包括本模块均可访问;
      #USE# Module1;      //使用模块Module1;
      ff(5)+gg(6);        //函数ff()和gg()在模块Module1中定义;


    在其他模块中使用该模块的格式如下:

      #USE# myModule;     //关键字USE必须为大写,myModule是模块名称;
      f(2)+g(3);          //调用myModule模块中定义的函数;


1.9 执行模块:void _stdcall ExeModule(void *hModule,void (_stdcall *outlu)(LuData *LD));

    hModule:编译源程序时得到的模块的句柄。
    outlu:输出表达式的值。这个回调函数在执行表达式时被调用,输出信息。该参数可设为NULL。
    注意1:该函数只执行模块中的无参表达式。
    注意2:
当Lu键树中有一个被锁定为字符串的键给出运行错误说明时,MLu将试图找出出现运行错误的原因。请参考键mluErrStr的说明。

1.10 删除模块:void _stdcallDelModule(void *hModule);

    hModule:编译源程序时得到的模块的句柄。


2 如何加载使用MLu  [目录]

2.1 MLu的加载和卸载

    (1)隐式调用

    使用MLu核心库的导入库文件mlu32.lib。这种方法比较方便。

    (2)显示调用

    应用程序可调用LoadLibrary直接加载MLu32.dll。

    HANDLE hMLu;           //动态库模块句柄
    hMLu=LoadLibrary(L"MLu32.dll");   
//加载动态库MLu32.dll

    加载MLu32.dll成功后,需调用函数GetProcAddress获取MLu输出函数的地址。例如:

    mluInitMLu pInitMLu;   //mluInitLu 在头文件Lu32.h中定义,为初始化MLu的函数指针;
    pInitMLu=(mluInitLu) GetProcAddress(hMLu,"InitMLu");

    该函数获得了初始化MLu的函数地址,保存在指针pInitMLu中。

    当程序不再需要访问MLu32.dll时,应调用函数FreeLibrary将其卸载。

    FreeLibrary(hMLu);    //释放动态库MLu32.dll;

2.2 MLu使用说明

    MLu加载成功后,必须先用函数InitMLu进行初始化;在卸载MLu之前,要用函数FreeMLu释放使用的资源。

    因MLu对多线程中使用Lu提供了支持,故在使用Lu及MLu的许多输出函数时,须先使用函数UseLu获得使用Lu的许可,并在用完Lu后,及时归还Lu资源的使用权。参见下表:

函  数说    明来 源是否需要UseLu
InitMLu初始化MLu。MLu
FreeMLu释放MLu。MLu
GetLuHandle得到Lu32W.dll的句柄。MLu
GetLuProc得到Lu32W.dll的输出函数。MLu
LoadDll加载Lu扩展动态库。MLu
FreeDll释放Lu扩展动态库。MLu
UseLu申请进入或退出Lu工作区。MLu
ComModule编译源程序为一个模块。MLu
ExeModule执行程序(模块)。MLu
DelModule删除模块。MLu
InitLu初始化Lu。Lu核心库禁止使用该函数
FreeLu释放Lu。Lu核心库禁止使用该函数
GetRunErr获得Lu运行错误。Lu核心库
TestRunErr测试Lu运行错误。Lu核心库
SetRunErr设置Lu运行错误。Lu核心库
GC垃圾收集。Lu核心库部分需要UseLu
Lu核心库的其他输出函数除了GetRunErr()、TestRunErr()、SetRunErr()GC()的之外的Lu核心库函数。Lu核心库

    在主调程序中可以设置(并非强制设置)一个全局变量int QuitMLu=0。然后将该变量的地址用InsertKey("mluQuit",7,luPriKey_User,&QuitMLu,DelKey,NULL,0,v)传送给Lu。当QuitMLu!=0时将退出MLu。规定仅在主线程中设置和修改该变量,但该变量可被任一线程所访问。

    在主调程序或任一个Lu扩展动态库中均可以设置一个函数int_stdcall mluLoadModule(wchar_t *ModuleName)。然后将该函数的地址用InsertKey("mluLoadModule",13,luPubKey_User,mluLoadModule,NULL,NULL,0,v)传送给Lu,这样MLu就可以编译模块(每当遇到#USE#myModule语句,就将myModule传送给该函数进行处理);若不传送该函数,MLu就不能编译模块。该函数接受一个模块名,然后返回该模块的编译代码,代码的意义与函数ComModule(...)返回的编译代码意义相同(实际上,只有-6和-7两个代码须由该函数处理)。该函数必须能判断是否进行了模块的递归调用。任一线程均可设置该函数。

    在主调程序或任一个Lu扩展动态库中均可以设置一个函数void _stdcallLuMessage(wchar_t *)。然后将该函数的地址用InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,0,v)传送给Lu。按约定,Lu核心库及所有Lu扩展库都使用该函数发送信息。任一线程均可根据需要设置该函数。

    在主调程序中可用Lu的加锁函数LockKey锁定一个键的类型为字符串,然后将被锁定的键KeyTypeInsertKey("mluErrStr",9,luPriKey_User,KeyType,DelKey,NULL,0,v)传送给Lu,这样MLu就可以给出更详细的运行错误说明。实际上,当出现运行错误时,MLu查找与出错函数名相同的键,键的类型为KeyType,其键值为一个字符串,该字符串包含了出错原因。该字符串格式如下:

    #-2:...; #-1:...; #1:...; #2:错误2; #3:...; ... ...

    例如,当运行错误代码为2时,将输出“#2:错误2;”中的“错误2”。每一个错误描述以“#”开头,后面紧跟错误代码和一个冒号“:”,冒号“:”后为错误说明,错误说明以分号“;”结尾。

    请参考函数ExeModuleerr的说明。

2.3 使用MLu的一般步骤

    (1)使用函数InitMLu进行初始化(必须)。

    (2)使用函数LoadDll加载需要的Lu扩展库。

    (3)使用函数ComModule将字符串源代码编译为模块(必须)。

    (4)使用函数ExeModule执行模块,或者使用函数GetFor获取需要的表达式进行计算(必须)。

    (5)使用函数SearchKey验证操作数据的类型,然后进行数据传送操作。

    (6)使用函数FreeDll卸载Lu扩展库。

    (7)使用函数FreeMLu释放资源(必须)。


3 二级函数  [目录]

3.1 MLu版本信息:mluver();

3.2 检测输出并清除Lu运行错误:err();

    检测到错误时,该函数返回错误类型代码。错误类型代码如下:

    0:没有运行错误!
    1:表达式运行错误!
    2:父表达式(基表达式)被删除!
    3:二级函数被删除!
    其他非0值:
其他运行错误!

    注意:当Lu键树中有一个被锁定为字符串的键给出运行错误说明时,MLu将试图找出出现运行错误的原因。请参考键mluErrStr的说明。

3.3 获得Lu运行错误:geterr(FunName,&FunCode,&ForHandle);

    FunName:Lu字符串。返回出错函数名;若字符串长度太小,仅返回部分函数名;若不是一个字符串,什么也不做。当返回值等于2或3时,返回空字符串。
    FunCode:当返回值等于1时,返回函数错误代码。当返回值等于2或3时,返回0。
    ForHandle:返回出错表达式的句柄,该句柄即编译表达式时获得的句柄。若ForHandle=0,则运行出错的表达式已被销毁。

    返回值:运行错误的类型。返回值=0:没有运行错误;返回值=1:表达式运行错误;返回值=2:父表达式被删除,父表达式即该表达式中所调用的表达式,也称基表达式;返回值=3:该表达式中所调用的二级函数被删除;返回值=其它值:其它类型运行错误。

    例子:f(:a,b,c,d)= seterr[66,"aaa",23], a=geterr[b="\[10]",&c,&d], o[b];

3.4 设置Lu运行错误:seterr(ErrType,FunName,FunCode);

    ErrType:设置运行错误的类型。ErrType=0:没有错误;ErrType=1:表达式运行错误;不要设置ErrType=2或ErrType=3,这两个值由系统自动设置;ErrType=其它值:其它类型运行错误。
    FunName:设置出错的函数名,要求传递一个Lu字符串(长度小于255)。
    FunCode:设置函数错误代码。

    返回值:false:非法的Lu字符串地址、ErrType=2或ErrType=3;true:成功返回。

    例子:f(:a,b,c,d)= seterr[66,"aaa",23], a=geterr[b="\[10]",&c,&d], o[b];

3.5 清除Lu运行错误:clearerr();

3.6 停止函数:stop[];

    该函数并不立即停止执行程序,只是在执行完本表达式后停止程序的执行。
    若要立即停止程序的执行,需要在stop[]函数后紧跟一个从表达式立即返回的函数return[]。
    例如:

      {stop[],o["停止程序!"]};//输出了字符串之后,停止程序执行;
      {stop[].return[],o["本字符串不会输出!"]}; //立即停止程序执行;

3.7 输出控制函数:SetTalk[bool];

    缺省情况下,MLu的ExeModule()函数每计算完一个表达式,就输出该表达式的值。SetTalk[]函数用于设置是否输出表达式的值。当bool为true时,输出表达式的值;当bool为false时,不输出表达式的值,直到再一次遇到SetTalk[true]。注意当bool为false时,并不关闭其他函数的输出。

3.8 编译源程序为一个模块:ComModule(Str,&nModule,&hModule,&err1,&err2);

    Str:源程序字符串;
    nModule:当
nModule为0时,所有模块的模块号自动指定(MLu初始化时,设置最初的起始模块号为1,以后不断递增,但不一定连续,因为每次执行该函数,不管是否执行成功,模块号均加1),不会重复,也不会被编译为0#模块。任何时候,可用nModule传送给MLu一个起始模块号(必须大于0),以后的模块号将在该模块号的基础上递增,从而改变模块号序列。若要自己指定模块号,则每次编译源程序前,均指定一个起始模块号。MLu编译的多个模块序号是递增的,但不一定连续,因为如果MLu加锁一个模块不成功,就会继续加锁下一个模块号。函数返回时,nModule返回多个模块的最小模块号。一般返回主模块号,如果主模块中没有表达式,就返回有表达式的最小子模块号。
    hModule:返回模块的句柄。当该模块不用时,就用delete(hModule)立即销毁该模块,否则将导致某些全局函数无法编译。
    err1err2:返回编译出错位置,该值是否有意义取决于函数的返回值(返回值为-1、0、1、3、-2时无意义)。

    该函数返回值的意义参考MLu的输出函数ComModule的说明。

    例子:

mvar:
main(:a)=
  t0=clock(), s=0, i=0,
  while{++i<=10000,
    //动态编译模块,该模块有2个函数,f为私有函数,ff为全局函数
    ComModule["f(x)=x+1; :::ff(x,y)=f(x)+y;",0,&me,0,0],
    a=HFor("ff"), //获得函数ff的句柄
    s=s+a[1,1],   //动态调用函数ff
    delete[me]    //立即销毁模块
  },
  s;
[clock()-t0]/1000.;



4 模块源文件  [目录]

4.1 源程序的一般格式 [目录]

    在MLu源文件中,可以有多个Lu表达式,表达式之间用分号“;”隔开。两个连续的分号“;;”表示前面的表达式在执行时不会输出结果。
    若表达式以mvar:开头,表示自该表达式开始,后面的表达式允许使用未定义的模块变量;若表达式以unmvar:开头,表示取消这种设置。mvar:unmvar:仅在当前模块起作用。
    在源文件中可以进行注释,注释方法与C++语言相似,即:每行两个//后的内容为注释内容;在一行内或者多行之间/*...*/之间的内容为注释内容。注释不是源程序的有效部分,但可以使程序更易读。

    举例如下:

    //这是一个例子!灰色部分为注释,不会被执行;
    2+3;            //整数表达式
    2.2+3.3;        //实数表达式
    sin(2.2+3.3i);  //复数表达式
    2+3;/* 从这里开始,连续几行注释:
    333+222;
    . . . . . . ;
    555-222;
    */ sin(2.5);
    exp(2.);


4.2 程序的执行  [目录]

    由于表达式有些带有参数,有些不带参数,MLu在进行处理时,对于有参数的表达式只进行编译,不进行计算。
    MLu只顺序执行不带参数的表达式。如果该表达式以两个连续的分号“;;”结尾,则该表达式只执行,不输出计算结果。
    但是,如果表达式以~~~开头,则无论是有参表达式还是无参表达式,都是只编译,不执行,格式如下:

    ~~~ 2+3;            //整数无参表达式,只编译,不执行
    ~~~ f1()=2+3;       //整数无参表达式,只编译,不执行
    ~~~ 2.0+3;          //实数无参表达式,只编译,不执行
    ~~~ f2()=2+3.0;     //实数无参表达式,只编译,不执行
    ~~~ 2+3i;           //复数无参表达式,只编译,不执行
    ~~~ f3()=2+3i;      //复数无参表达式,只编译,不执行


    无参表达式f1、f2和f3可以在其他可执行的表达式中被调用。

    另外,如果无参表达式以感叹号!!!开头,则编译后立即执行,且以后执行模块时不再自动执行。格式如下:

    !!! 2+3;            //整数无参表达式,编译成功,立即执行,以后不再自动执行
    !!! f1()=2+3;       //整数无参表达式,编译成功,立即执行,以后不再自动执行
    !!! 2.0+3;          //实数无参表达式,编译成功,立即执行,以后不再自动执行
    !!! f2()=2+3.0;     //实数无参表达式,编译成功,立即执行,以后不再自动执行
    !!! 2+3i;           //复数无参表达式,编译成功,立即执行,以后不再自动执行
    !!! f3()=2+3i;      //复数无参表达式,编译成功,立即执行,以后不再自动执行


    无参表达式f1、f2和f3可以在其他可执行的表达式中被调用。

4.3 源程序中的模块 [目录]

    编译时,将源程序中的表达式编译为一个或多个模块,MLu会对每一个模块进行加锁。编译时首先设置起始模块,也称主模块(并非Lu的0#模块,恰恰相反,MLu不会将任何一个表达式编译为0#模块,定义主模块是为了与源程序中的其他模块相区别),以后每当遇到#MODULE#,开始编译为一个新的模块,称为子模块,而每当遇到#END#,回到主模块的编译。即#MODULE##END#之间的表达式定义为一个子模块,子模块之间不能嵌套定义。注意#MODULE##END#必须位于表达式的开头。

    在模块中,以:::开头的表达式被编译为公有表达式(全局表达式或全局函数),能被其他模块访问到,其余的表达式均被编译为私有表达式(私有函数),其他模块无法访问。所有模块的模块号由MLu或程序员指定,不会重复,也不会被编译为0#模块。在源程序的任何地方,可用指令#USE#调用另一个模块。

    模块源文件的格式如下:

      //单行注释:模块名:myModule
      /*
        多行注释:在同一模块源文件中的所有表达式属于同一个模块;
        多行注释:以~开头的表达式可被其他模块的表达式所访问;
        多行注释:不以~开头的表达式只能被该模块的表达式所访问。
      */
      #MODULE#               //定义一个子模块;
        a(x)=10+x;           //私有函数,只能被该模块的表达式所访问;
        !!!b()=100+100i;     //私有函数,只能被该模块的表达式所访问,该表达式是在编译时执行的;
        :::c(x)=x-5;         //全局函数,任意模块包括本模块均可访问;
        :::f(x)=a(x)+b();    //全局函数,任意模块包括本模块均可访问;
        :::g(x)=a(x)+c(x);   //全局函数,任意模块包括本模块均可访问;
        #USE# Module1;       //使用模块Module1;
        ff(5)+gg(6);         //函数ff()和gg()在模块Module1中定义;
      #END#                  //子模块定义结束,可缺省;
      #MODULE#               //定义一个子模块;
        a(x)=10-x;           //私有函数,只能被该模块的表达式所访问;
        :::ff(x)=a(x);       //全局函数,任意模块包括本模块均可访问;
      #END#                  //子模块定义结束,不可缺省;
      f(1);                  //主模块中的表达式。
      ff(1);                 //主模块中的表达式。


    在其他模块中使用该模块的格式如下:

      #USE# myModule;       //关键字USE必须为大写,myModule是模块名称;
      f(2)+g(3);             //调用myModule模块中定义的函数;

4.4 编译指令的位置和次序 [目录]

    在MLu中使用的 #MODULE##END##USE#mvar:unmvar::::!!!~~~ 等称为编译指令,用以确定一个表达式所在模块、是否私有函数等属性。这些编译指令必须位于表达式的开头,有些指令能同时使用,有些指令不能同时使用,并且在使用时有一定的次序,按先后顺序依次为:

    1)编译指令#MODULE##END##USE#mvar:unmvar:之间没有先后顺序,可混合使用,但这些指令必须在表达式的最前面,一般单独成行。注意mvar:unmvar:只在本模块内有效。

    2)编译指令!!!~~~不能混合使用,只能使用其中的一个。~~~表示该表达式只编译,不执行;!!!表示该表达式编译后立即执行,但以后执行模块时不再自动执行。

    3):::表示该表达式是一个全局表达式,否则是私有表达式。

    如果表达式前没有使用任何一个编译指令,则按缺省表达式的类型编译为私有表达式,若该表达式是无参表达式,则执行模块时将自动执行。


5 例子  [目录]

5.1 隐式加载例子

    该例子需要以下支持文件:

    (1)头文件lu32.h。
    (2)导入库lu32.lib及mlu32.lib。
    (3)核心库lu32.dll和模块化编译运行库mlu32.dll。

#include <windows.h>
#include <iostream>
#include "lu32.h"			//Lu头文件
#pragma comment( lib, "lu32.lib" )
#pragma comment( lib, "mlu32.lib" )
using namespace std;
void main(void)
{
	void *hModule;		//模块句柄
	luINT ErrBegin,ErrEnd;	//表达式编译出错的初始位置和结束位置
	int i;			//错误代码
	void *hFor;		//表达式句柄
	luVOID nModule=0;		//表达式所在模块
	void *vPara;		//存放输入自变量的数组指针
	LuData *pPara;		//存放输入自变量的数组指针
	luINT nPara;		//存放表达式的自变量个数
	LuData Val;		//存放表达式的值
	wchar_t ForStr[]=L"f(x)=x+1; :::ff(x,y)=f(x)+y;";	//Lu模块化源程序
	if(!InitMLu()) return;	//初始化MLu
	if(!UseLu(2))		//申请使用Lu资源
	{
		i=ComModule(ForStr,nModule,hModule,ErrBegin,ErrEnd);	//编译Lu源程序
		if(i)
		{
			cout<<"Lu源程序有错误!错误代码:"<<i<<endl;
		}
		else
		{
			if(GetFor(L"ff",1,NULL,nModule,hFor,vPara,nPara))	//查找全局函数
			{
				pPara=(LuData *)vPara;
				for(i=0;i<=nPara;i++)	//表达式自变量赋值,均赋值为1
				{
					pPara[i].BType=luStaData_int64; pPara[i].VType=luStaData_int64; pPara[i].x=1;
				}
				Val=LuCal(hFor,pPara);	//计算表达式的值
				cout<<Val.x<<endl;
			}
			else
			{
				cout<<"找不到指定的函数!"<<endl;
			}
		}
		UseLu(0);		//归还Lu的使用权
	}
	FreeMLu();		//释放MLu
}


    结果:

3
请按任意键继续. . .

5.2 显式加载例子

    该例子需要以下支持文件:

    (1)头文件lu32.h。
    (2)核心库lu32.dll和模块化编译运行库mlu32.dll。

#include <windows.h>
#include <iostream>
#include "Lu32.h"
using namespace std;
HINSTANCE hMLu=NULL;	//动态库MLu32.dll的句柄

//MLu输出函数
mluInitMLu pInitMLu;
mluFreeMLu pFreeMLu;
mluGetLuProc pGetLuProc;
mluUseLu pUseLu;
mluComModule pComModule;
//Lu输出函数
luGetFor pGetFor;
luLuCal pLuCal;
bool theInitMLu(void)	//初始化MLu
{
	hMLu=LoadLibrary(L"MLu32.dll");	//加载动态库MLu32.dll
	if(!hMLu)
	{
		cout<<"找不到MLu32.dll!请将该库放到WINDOWS的搜索路径内!";
		return false;
	}
	//以下几个语句获取MLu32.dll的输出函数
	pInitMLu=(mluInitMLu) GetProcAddress(hMLu,"InitMLu");
	pFreeMLu=(mluFreeMLu) GetProcAddress(hMLu,"FreeMLu");
	pGetLuProc=(mluGetLuProc) GetProcAddress(hMLu,"GetLuProc");
	pUseLu=(mluUseLu) GetProcAddress(hMLu,"UseLu");
	pComModule=(mluComModule) GetProcAddress(hMLu,"ComModule");
	if(!pInitMLu())	//初始化MLu32.dll
	{
		FreeLibrary(hMLu);	//释放动态库
		cout<<"MLu初始化失败!";
		return false;
	}
	//以下几个语句获取Lu32.dll的输出函数
	pGetFor=(luGetFor) pGetLuProc("GetFor");
	pLuCal=(luLuCal) pGetLuProc("LuCal");
	return true;
}
void theFreeMLu(void)	//释放MLu
{
	pFreeMLu();	//释放MLu申请的空间
	FreeLibrary(hMLu);	//释放动态库
}
void main(void)
{
	void *hModule;		//模块句柄
	luINT ErrBegin,ErrEnd;	//表达式编译出错的初始位置和结束位置
	int i;			//错误代码
	void *hFor;		//表达式句柄
	luVOID nModule=0;		//表达式所在模块
	void *vPara;		//存放输入自变量的数组指针
	LuData *pPara;		//存放输入自变量的数组指针
	luINT nPara;		//存放表达式的自变量个数
	LuData Val;		//存放表达式的值
	wchar_t ForStr[]=L"f(x)=x+1; :::ff(x,y)=f(x)+y;";	//Lu模块化源程序
	if(!theInitMLu()) return;	//初始化MLu
	if(!pUseLu(2))		//申请使用Lu资源
	{
		i=pComModule(ForStr,nModule,hModule,ErrBegin,ErrEnd);	//编译Lu源程序
		if(i)
		{
			cout<<"Lu源程序有错误!错误代码:"<<i<<endl;
		}
		else
		{
			if(pGetFor(L"ff",1,NULL,nModule,hFor,vPara,nPara))
			{
				pPara=(LuData *)vPara;
				for(i=0;i<=nPara;i++)	//表达式自变量赋值,均赋值为1
				{
					pPara[i].BType=luStaData_int64; pPara[i].VType=luStaData_int64; pPara[i].x=1;
				}
				Val=pLuCal(hFor,pPara);	//计算表达式的值
				cout<<Val.x<<endl;
			}
			else
			{
				cout<<"找不到指定的函数!"<<endl;
			}
		}
		pUseLu(0);	//归还Lu的使用权
	}
	theFreeMLu();		//释放MLu
}


    结果:

3
请按任意键继续. . .


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值