`
ideaforj
  • 浏览: 71259 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

FORCAL32W.DLL V9.0 编程指南

 
阅读更多

FORCAL32W.DLL V9.0 编程指南

目  录

1 输出函数
2 简单计算
3 FORCAL二级函数设计
4 FORCAL的基本用法
5 Forcal软件组成与使用
6 用FORCAL保存和检索数据

Forcal 输 出 函 数

1.1  版本信息函数:ForcalVer
1.2  初始化FORCAL:InitForcal
1.3  释放FORCAL:FreeForcal
1.4  获得FORCAL运行错误:GetRunErr
1.5  测试FORCAL运行错误:TestRunErr
1.6  设置FORCAL运行错误:SetRunErr
1.7  编译实数表达式:RealCom
1.8  计算实数表达式的值:RealCal
1.9  编译整数表达式:IntCom
1.10 计算整数表达式的值:IntCal
1.11 编译复数表达式:ComplexCom
1.12 计算复数表达式的值:ComplexCal
1.13 锁定一个模块:LockModule
1.14 设置外部二级函数:SetFunction
1.15 设置常量:SetConst
1.16 删除常量或二级函数:DeleteConstOrFunction
1.17 判断一个表达式是否有效:IsFor
1.18 获得表达式信息:GetFor
1.19 判断表达式的自变量是否重新赋值:ParaModify
1.20 获得表达式中的字符串:GetForStr
1.21 删除一个表达式:DeleteFor
1.22 插入一个键:InsertKey
1.23 查找一个键:SearchKey
1.24 删除一个键:DeleteKey
1.25 删除一个私有键:DeletePrivateKey
1.26 枚举指定键值类型所对应的所有字符串及键值:EnumKeyTypeValue
1.27 锁定键的类型:LockKeyType
1.28 与Forcal交换信息:ExMsgWithForcal
1.29 插入一个指针键:InsertKeyP
1.30 垃圾收集时标记一个指针键(对象):SignGoodObj
1.31 垃圾收集:GC

    FORCAL 用Win32标准函数调用方式(stdcall调用协议)输出了动态库函数,可供C/C++、VB、delphi、FORTRAN等程序使用。

    除了GetRunErr()、 TestRunErr()和SetRunErr() 三个函数外,其余的函数只能在单线程中使用(不允许两个及两个以上的线程同时运行这些函数),在设计多线程应用程序时必须注意这一点。

    Forcal不抛出异常,如果在主调程序中检测到了异常,可能来自于外部模块向Forcal注册的函数,此时,可尝试对Forcal重新进行初始化。

    并行计算设想: 在 多核计算机中进行并行运算时,可复制Forcal32W.dll为多个副本Forcal32W1.dll、Forcal32W2.dll、... ...,同时加载Forcal32W.dll及各个副本,Forcal32W.dll及各个副本都有自己的地址空间,可独立运行互不影响,这样可实现并行 计算。

    以下是FORCAL中使用的一些整数类型定义:

    typedef __int64 fcIFOR;    //FORCAL表达式中的整数类型定义
    typedef __int32 fcVOID;   
//FORCAL的指针型整数定义
    typedef __int32 fcINT;    
//FORCAL的通用整数定义
    typedef __int32 fcKEY;    
//FORCAL的键值定义

    在编写代码时, 应注意能方便地移植到64位平台。为此 约定:指针总是保存在Forcal数据(整数、实数或复数)前面的字节中,例如在32位平台上,指针应保存在数据的前4个字节中。保存一个指针的代码如下:

    fcIFOR fci;                    //定义一个FORCAL整数
    void *p;                       //定义一个指针

    p=... ...;                     //指针赋值
    *(fcVOID *)&fci=(fcVOID)p;     //指针p保存在整数fci的前面的字节中,无论32位平台还是64位平台均可正常编译

1 输出函数 [返回页首 ]

1.1 版本信息函数: ForcalVer

    const wchar_t * _stdcall ForcalVer(void);

1.2 初始化FORCAL: InitForcal

    bool _stdcall InitForcal(void);

    在使用Forcal前必须先用该函数进行初始化。初始化成功时返回true,否则返回false。
    可在任何时刻使用该函数对Forcal进行重新初始化,使Forcal恢复到第一次调用该函数时的状态。
    重新初始化时,若在Forcal键树中有未删除的表达式,在删除表达式之前将不会重置静态变量free为1并执行该表达式,也不会销毁由静态变量free 或函数free标识的对象。要实现删除表达式之前的这种自动执行效果,应使用函数DeleteFor自己删除表达式。关于在删除一个表达式前要做的这些工 作,请参考函数
DeleteFor 的说明。

1.3 释放 FORCAL:FreeForcal

    void _stdcall FreeForcal(void);

    只要使用了FORCAL动态库函数,在卸载动态库之前,必须用该函数释放动态库。
    释放Forcal时,若在Forcal键树中有未删除的表达式,在删除表达式之前将不会重置静态变量free为1并执行该表达式,也不会销毁由静态变量 free或函数free标识的对象。要实现删除表达式之前的这种自动执行效果,应使用函数DeleteFor自己删除表达式。关于在删除一个表达式前要做 的这些工作,请参考函数
DeleteFor 的说明。

1.4 获得FORCAL运行错误: GetRunErr

    void _stdcall GetRunErr(int &ErrType,wchar_t *&FunName,int &FunCode,int &ForType,void *&ForHandle);

    ErrType:返回运行错误的类型。ErrType=0:没有运行错误;ErrType=1:整数函数运行错误;ErrType=2:实数函数运行错 误;ErrType=3:复数函数运行错误;ErrType=4:父表达式被删除,父表达式即该表达式中所调用的表达式,也称基表达 式;ErrType=5:该表达式中所调用的二级函数被删除;ErrType=其它值:其它类型运行错误。
    FunName:当ErrType=1、ErrType=2或ErrType=3时,返回出错函数名。当ErrType=4或ErrType=5时,返回0。
    FunCode:当ErrType=1、ErrType=2或ErrType=3时,返回函数错误代码。当ErrType=4或ErrType=5时,返回0。
    ForType:返回出错表达式的类型。ForType=1表示整数表达式,ForType=2表示实数表达式,ForType=3表示复数表达式。
    ForHandle:返回出错表达式的句柄,该句柄即编译表达式时获得的句柄。若ForHandle=0,则运行出错的表达式已被销毁。

    FORCAL在运行时,将记录出现的第一个运行错误。
    通常在编译表达式前后和执行表达式前后使用该函数。使用该函数后,FORCAL将恢复为无错状态。
    在编译和执行表达式后使用该函数,是为了检测发生的运行错误。之所以还要在编译和执行表达式前使用该函数(在编译和执行表达式前,应保证没有运行错误,如 果确信无错,也可以不用该函数),是因为该函数可将FORCAL恢复为无错状态;当然,也可以用SetRunErr()函数直接设为无错状态。

1.5 测试FORCAL运行错误:TestRunErr

    int _stdcall TestRunErr(void);

    该函数返回FORCAL运行错误的类型,当返回0时表示没有错误。该函数仅仅测试是否有运行错误,并不改变错误的状态。
    通常在二级函数设计中要用到该函数。

1.6 设置FORCAL运行错误:SetRunErr

    void _stdcall SetRunErr(int ErrType,wchar_t *FunName,int FunCode,int ForType,void *ForHandle);

    ErrType:设置运行错误的类型。ErrType=1:整数函数运行错误; ErrType=2:实数函数运行错误; ErrType=3:复数函数运行错误; 不要设置ErrType=4或ErrType=5,这两个值由系统自动设置;ErrType=其它值:其它类型运行错误。
    FunName:设置出错的函数名,要求传递一个静态字符串。
    FunCode:设置函数错误代码。
    ForType:设置出错表达式的类型。ForType=0表示任意表达式。ForType=1表示整数表达式,ForType=2表示实数表达式,ForType=3表示复数表达式。
    ForHandle:设置出错表达式的句柄。当ForType=0时的句柄为从二级函数获得的表达式句柄。当ForType=1、ForType=2或ForType=3时的句柄为编译表达式时获得的句柄。

    在设计自定义的二级函数时,可以用该函数设置FORCAL运行错误。由于FORCAL只保存出现的第一个运行错误,因此在设置之前,先用TestRunErr函数测试是否出现过运行错误,如果还没有出现,可以进行设置,否则,不能进行设置。

    FORCAL允许另一个线程修改运行时的出错状态,以便退出FORCAL运行,因此可在其它线程中使用SetRunErr()函数设置运行错误。

1.7 编译实数表达式:RealCom

    int _stdcall RealCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,double *&Para,fcINT &ErrBegin,fcINT &ErrEnd);

    ForStr:字符串表达式。
    nModule:模块号。每一个模块都有自己的模块变量空间,为了提高存储效率,编译时尽量减少模块的数目。
    hFor:输入参数为加锁模块的函数指针,可以为0。返回时获得一个表达式句柄,标识一个表达式,计算表达式的值时要用到该参数。该参数必须为变量,不能为常量。
        typedef void (_stdcall *FcNullLock)(void);    //加锁模块的函数指针;
        void _stdcall NullLock(void){};               //加锁模块的函数定义;
        如果预先用函数LockModule (hModule,NullLock,true) 对一个模块hModule 加锁,则编译表达式时必须提供加锁函数的指针,否则无法编译。缺省情况下,Forcal对任何模块都不会加锁。
    nPara:该参数必须为变量,不能为常量。该参数返回表达式的自变量个数。当nPara=-1时表示有0个自变量,当nPara=0时表示有1个自变量,当nPara=1时表示有2个自变量,依次类推。
    Para:该参数必须为变量,不能为常量。该参数返回用于输入自变量的数组指针。计算表达式的值时要用到该参数。当然,也可以不用该参数,而用自己的数组输入自变量。
    ErrBegin:该参数必须为变量,不能为常量。该参数返回出错的初始位置。
    ErrEnd:该参数必须为变量,不能为常量。该参数返回出错的结束位置。
    该函数返回编译代码,当返回值为0时,表示没有错误,当返回其它值时,表示存在编译错误,出错位置由ErrBegin和ErrEnd确定。编译错误代码的意义如下:

    -2:模块加锁函数不正确。 该返回值由程序员进行处理!
    -1:未用!
    0:没有错误,编译成功!
    1:内存分配失败!
    2:括号不成对!
    3:(等号后)没有表达式!
    4:复数表达式中不能使用i作为参数!
    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:运算符重载函数oo有0个自变量或嵌套使用!
    38:未用!
    39:源代码太长或字符串太多!

    通常在编译前用SetRunErr()函数或GetRunErr()函数使FORCAL处于无错状态,编译后用GetRunErr()检测运行错误。其他线程的错误设置可使FORCAL退出漫长的编译过程,返回错误代码36。

    FORCAL支持表达式的模块化编译。在用FORCAL编译表达式时,要给该表达式指定一个模块号,模块号用整数进行标识。如果用模块加锁函数LockModule 对一个模块号进行了加锁,则编译表达式时必须提供加锁函数。

    在FORCAL中,一个模块由一个或多个表达式组成。模块用一个整数标识,整数可正可负,只要绝对值相等,就属于同一个模块。一般用正整数表示该模块名。模块共有两类,即主模块(0#模块)和普通模块(其他标号的模块)。

    同一模块中,模块号为负的表达式称私有表达式,只能被本模块的表达式所访问(即调用),在其他模块中是不可见的;模块号为正的表达式称公有表达式或全局表 达式,能被任何一个表达式所访问。主模块(0#模块)中的表达式都是私有表达式。任何一个表达式,既可以访问本模块中的表达式,也可以访问其他模块中的全 局表达式,如果本模块中的一个私有表达式与其他模块的一个全局表达式重名,将优先调用本模块中的私有表达式。

    由以上规定可以看出,主模块可以访问本模块中的表达式,也可以访问其他模块中的全局表达式。因此,主模块常常用在主程序中。

    注:在编译表达式时,缺省情况下,所有用到的模块变量必须预先定义。可用函数 ExMsgWithForcal Type为12,hMsg非0)通知编译器使用未定义的模块变量(若一个标识符没有定义,且不是常量,将被解释为模块变量);也可用函数 ExMsgWithForcal Type为12, hMsg为0)通知编译器取消这种设置。无论表达式编译是否成功,将恢复缺省设置,即:所有用到的模块变量必须预先声明。

    表达式hFor的销毁:(1)使用函数 DeleteFor 销毁表达式;(2)重新初始化Forcal时由函数 InitForcal 销毁所有表达式;(3)释放Forcal时由函数 FreeForcal 销毁所有表达式。

1.8 计算实数表达式的值:RealCal

    double _stdcall RealCal(void *hFor,double *d);

    计算实数表达式hFor,hFor是实数表达式的句柄;数组d中依次存放自变量,参数d不可为NULL。可以用任意的数组存放自变量参数。
    注意自变量可能被重新赋值。可以用
ParaModify ()函数判断一个表达式的自变量是否重新赋值。
    通常在计算前用SetRunErr()函数或GetRunErr()函数使FORCAL处于无错状态,计算后用GetRunErr()检测运行错误。

1.9 编译整数表达式:IntCom

    int _stdcall IntCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,fcIFOR *&Para,fcINT &ErrBegin,fcINT &ErrEnd);

    ForStr:字符串表达式。
    nModule:模块号。每一个模块都有自己的模块变量空间,为了提高存储效率,编译时尽量减少模块的数目。
    hFor:输入参数为加锁模块的函数指针,可以为0。返回时获得一个表达式句柄,标识一个表达式,计算表达式的值时要用到该参数。该参数必须为变量,不能为常量。
        typedef void (_stdcall *FcNullLock)(void);    //加锁模块的函数指针;
        void _stdcall NullLock(void){};               //加锁模块的函数定义;
        如果预先用函数LockModule (hModule,NullLock) 对一个模块hModule 加锁,则编译表达式时必须提供加锁函数的指针,否则无法编译。缺省情况下,Forcal对任何模块都不会加锁。
    nPara:该参数必须为变量,不能为常量。该参数返回表达式的自变量个数。当nPara=-1时表示有0个自变量,当nPara=0时表示有1个自变量,当nPara=1时表示有2个自变量,依次类推。
    Para:该参数必须为变量,不能为常量。该参数返回用于输入自变量的数组指针。计算表达式的值时要用到该参数。当然,也可以不用该参数,而用自己的数组输入自变量。
    ErrBegin:该参数必须为变量,不能为常量。该参数返回出错的初始位置。
    ErrEnd:该参数必须为变量,不能为常量。该参数返回出错的结束位置。
    该函数返回编译代码,当返回值为0时,表示没有错误,当返回其它值时,表示存在编译错误,出错位置由ErrBegin和ErrEnd确定。
    通常在编译前用SetRunErr()函数或GetRunErr()函数使FORCAL处于无错状态,编译后用GetRunErr()检测运行错误。

    其它请参考“1.7 编译实数表达式”中的说明。

1.10 计算整数表达式的值:IntCal

    fcIFOR _stdcall IntCal(void *hFor,fcIFOR *d);

    计算整数表达式hFor,hFor是整数表达式的句柄;数组d中依次存放自变量,参数d不可为NULL。可以用任意的数组存放自变量参数。
    注意自变量可能被重新赋值。可以用
ParaModify ()函数判断一个表达式的自变量是否重新赋值。
    通常在计算前用SetRunErr()函数或GetRunErr()函数使FORCAL处于无错状态,计算后用GetRunErr()检测运行错误。

1.11 编译复数表达式:ComplexCom

    int _stdcall ComplexCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,_complex *&Para,fcINT &ErrBegin,fcINT &ErrEnd);

    ForStr:字符串表达式。
    nModule:模块号。每一个模块都有自己的模块变量空间,为了提高存储效率,编译时尽量减少模块的数目。
    hFor:输入参数为加锁模块的函数指针,可以为0。返回时获得一个表达式句柄,标识一个表达式,计算表达式的值时要用到该参数。该参数必须为变量,不能为常量。
        typedef void (_stdcall *FcNullLock)(void);    //加锁模块的函数指针;
        void _stdcall NullLock(void){};               //加锁模块的函数定义;
        如果预先用函数LockModule (hModule,NullLock) 对一个模块hModule 加锁,则编译表达式时必须提供加锁函数的指针,否则无法编译。缺省情况下,Forcal对任何模块都不会加锁。
    nPara:该参数必须为变量,不能为常量。该参数返回表达式的自变量个数。当nPara=-1时表示有0个自变量,当nPara=0时表示有1个自变量,当nPara=1时表示有2个自变量,依次类推。
    Para:该参数必须为变量,不能为常量。该参数返回用于输入自变量的数组指针。计算表达式的值时要用到该参数。当然,也可以不用该参数,而用自己的数组输入自变量。
    ErrBegin:该参数必须为变量,不能为常量。该参数返回出错的初始位置。
    ErrEnd:该参数必须为变量,不能为常量。该参数返回出错的结束位置。
    该函数返回编译代码,当返回值为0时,表示没有错误,当返回其它值时,表示存在编译错误,出错位置由ErrBegin和ErrEnd确定。
    通常在编译前用SetRunErr()函数或GetRunErr()函数使FORCAL处于无错状态,编译后用GetRunErr()检测运行错误。

    其它请参考“1.7 编译实数表达式”中的说明。

1.12 计算复数表达式的值:ComplexCal

    _complex _stdcall ComplexCal(void *hFor,_complex * d);

    计算复数表达式hFor,hFor是复数表达式的句柄;数组d中依次存放自变量,参数d不可为NULL。可以用任意的数组存放自变量参数。
    注意自变量可能被重新赋值。可以用
ParaModify ()函数判断一个表达式的自变量是否重新赋值。
    通常在计算前用SetRunErr()函数或GetRunErr()函数使FORCAL处于无错状态,计算后用GetRunErr()检测运行错误。

1.13 锁定一个模块:LockModule

    bool _stdcall LockModule(fcVOID hModule,void (_stdcall *NullLock)(void),bool bLock);

    hModule :模块号。
   
NullLock :模块加锁函数指针。模块加锁函数在主程序中定义,格式如下:

        void _stdcall NullLock(void){};       //加锁模块的函数定义;

    bLock :bLock=true,加锁模块;bLock=false,解锁模块。

    如果预先用函数LockModule(hModule,NullLock,true) 对一个模块hModule 加锁,则编译表达式时必须提供加锁函数的指针,否则无法编译。缺省情况下,Forcal对任何模块都不会加锁。

    通常,模块加锁后无需解锁,模块中没有表达式时将自动解锁。但如果模块加锁后从未使用(没有一个表达式编译成功),则需用函数LockModule(hModule,NullLock,false) 进行解锁。

    加锁一个模块使得其他线程无法向该模块中增加表达式,这在设计多线程程序时特别有用。

1.14 设置外部二级函数:SetFunction

    int _stdcall SetFunction(fcKEY FunType,wchar_t *FunName,void *Fun,fcINT ParaNum);

    FunType :二级函数类型。只能取Key_IntFunction (标识整数二级函数)、Key_RealFunction (标识实数二级函数)、Key_ComplexFunction (标识复数二级函数)。这三个标识符的值在头文件FORCAL32W.h 中定义。
    FunName :二级函数名称,要符合Forcal标识符的命名规定。
    Fun :二级函数指针。整数、实数、复数二级函数的函数说明格式如下:

      fcIFOR IntFun(fcINT m,fcIFOR *Para,void *hFor);        //FORCAL标准整数二级函数;
      double RealFun(fcINT m,double * Para ,void * hFor );        //FORCAL标准实数二级函数;
      _complex ComplexFun(fcINT m,_complex *
Para ,void * hFor ); //FORCAL标准复数二级函数;

    其中m为Forcal传递给该函数的实际的参数个数,-1表示有0个自变量,0表示有1个自变量,依次类推。Para为存放参数的数组。hFor为调用该函数的表达式句柄(与编译表达式时返回的表达式句柄并不相同)。
    在FORCAL表达式中,函数的一般形式为FunName(X1,X2,...,Xn)。
    ParaNum :存放二级函数的自变量个数。数组ParaNum的对应项存放每个函数的自变量个数,其中-2表示有不确定的多个自变量,-1表示有0个自变量,0表示有1个自变量,依次类推。
    该函数返回值的意义如下:

      0:设置成功。
      1:已存在该函数。
      2:内存分配失败。
      3:不能用空字符串作为函数名。
      4:非法的
二级函数类型标识。

    例子:

      double _stdcall asd(fcINT ,double * ,void * );        //自定义实数二级函数;
     
SetFunction ( Key_RealFunction,"asd",asd ,2);          //设置实数二级函数;

    注意:

      1、在设计二级函数时,通常要用SetRunErr(...)向FORCAL报告运行错误。
      2、通常在初始化FORCAL之后,立即进行二级函数的设置。
      3、设计二级函数必须使用_stdcall 调用协议(Win32标准函数调用方式)。
      4、函数参数如果是一个指针,约定指针保存在参数的前4个字节中。
      5、可以在整数和实数二级函数中返回一些临时对象,参考函数
ExMsgWithForcal (Type为15、16)的说明。

    取消设置的外部二级函数:(1)使用函数 DeleteConstOrFunction ;(2)重新初始化Forcal时由函数 InitForcal 取消所有外部二级函数;(3)释放Forcal时由函数 FreeForcal 取消所有外部二级函数。

1.15 设置常量:SetConst

    int _stdcall SetConst(fcKEY Const Type,wchar_t * Const Name,void * ConstValue);

    ConstType:常量类型。 只能取Key_IntConst (标识整数常量)、Key_RealConst (标识实数常量)、Key_ComplexConst (标识复数常量)。这三个标识符的值在头文件FORCAL32W.h 中定义。
    ConstStr :常量名, 要符合Forcal标识符的命名规定。
   
ConstValue :指向常量的值的指针。
    该函数返回值的意义如下:

      0:设置成功。
      1:已存在该常量。
      2:内存分配失败。
      3:不能用空字符串作为常量名。
      4:非法的常量类型标识。

    例如:

      double *pi=3.14;   //设置常量的值;
      SetConst (
Key_RealConst ,"pi",pi);    //设置常量;

    销毁设置的常量:(1)使用函数 DeleteConstOrFunction ;(2)重新初始化Forcal时由函数 InitForcal 销毁所有常量;(3)释放Forcal时由函数 FreeForcal 销毁所有常量。

1.16 删除常量或二级函数:DeleteConstOrFunction

    bool _stdcall DeleteConstOrFunction ( fcKEY Type,wchar_t *Name);

    Type:常量或函数类型。 只能取Key_IntConst (标识整数常量)、Key_RealConst (标识实数常量)、Key_ComplexConst (标识复数常量)、Key_IntFunction (标识整数二级函数)、Key_RealFunction (标识实数二级函数)、Key_ComplexFunction (标识复数二级函数)。这六个标识符的值在头文件FORCAL32W.h 中定义。
    Name:
常量或函数 名称,要符合Forcal标识符的命名规定。

    返回值:操作成功返回true,否则返回false。

1.17 判断一个表达式是否有效: IsFor

    bool _stdcall IsFor(wchar_t * ForName , fcKEY ForType,fcVOID nModule,void *hFor,void *Para,fcINT PareNum );

    用法1:

    ForName:表达式的名称,只能是简单名称,不能包含模块命名空间访问符::
    ForType:表达式的类型。只能取Key_IntFor (标识整数表达式)、Key_RealFor (标识实数表达式)、Key_ComplexFor (标识复数表达式)。这三个标识符的值在头文件FORCAL32W.h 中定义。
    nModule:表达式所属的模块。
    hFor:表达式句柄,该句柄即编译表达式得到的表达式句柄,可用于表达式的计算。
    Para:存放表达式自变量的数组指针。
    ParaNum:表达式自变量的个数。
    该函数返回true时表达式有效,返回false不是一个有效的表达式。

    用法2:

    ForName:ForName=NULL。
    ForType:表达式的类型。只能取Key_IntFor (标识整数表达式)、Key_RealFor (标识实数表达式)、Key_ComplexFor (标识复数表达式)。这三个标识符的值在头文件FORCAL32W.h 中定义。
    nModule:表达式所属的模块。
    hFor:表达式句柄,该句柄即编译表达式得到的表达式句柄,但必须由二级函数HFor获得,可用于表达式的计算。
    Para:存放表达式自变量的数组指针。
    ParaNum:表达式自变量的个数。
    该函数返回true时表达式有效,返回false不是一个有效的表达式。

1.18 获得表达式信息:GetFor

    bool _stdcall GetFor(wchar_t *ForName, fcKEY ForType,void *hFor,fcVOID &nModule,void *&myFor,void *&Para,fcINT &PareNum);

    用法1:

    ForName:所查询的表达式的名称。可以是简单名称,也可以是包含模块命名空间访问符::(该访问符可简化为一个或多个:) 的复杂名称。
    ForType:所查询的表达式的类型。如果是简单名称,只能取Key_IntFor (标识整数表达式)、Key_RealFor (标识实数表达式)、Key_ComplexFor (标识复数表达式)。如果名称包含模块命名空间访问符:: ,只能取-Key_IntFor (标识整数表达式)、-Key_RealFor (标识实数表达式)、-Key_ComplexFor (标识复数表达式)。标识符Key_IntForKey_RealForKey_ComplexFor 的值在头文件Forcal32W.h 中定义。
    hFor:若hFor!=NULL,hFor必须是从二级函数获得的表达式句柄,不能使用编译表达式得到的表达式句柄。若hFor=NULL,只能获得0号模块中的表达式的信息,或者是一个全局表达式的信息。
    nModule:该参数必须为变量,不能为常量。该参数返回一个表达式所属的模块。
    myFor:该参数必须为变量,不能为常量。该参数返回一个表达式句柄,该句柄与编译表达式得到的表达式句柄的类型相同,可用于表达式的计算。
    Para:该参数必须为变量,不能为常量。该参数返回一个存放表达式自变量的数组指针,可用于输入自变量。
    ParaNum:该参数必须为变量,不能为常量。该参数返回表达式自变量的个数。当ParaNum=-1时表示有0个自变量,当ParaNum=0时表示有1个自变量,当ParaNum=1时表示有2个自变量,依次类推。
    该函数返回true时查询成功,否则返回false。
    注意:若hFor!=NULL,则只能在二级函数中使用该函数;若hFor=NULL,可在任何时候使用该函数。

    用法2:

    ForName:ForName=NULL。
    ForType:表达式的类型。只能取Key_IntFor (标识整数表达式)、Key_RealFor (标识实数表达式)、Key_ComplexFor (标识复数表达式)。标识符Key_IntForKey_RealForKey_ComplexFor 的值在头文件Forcal32W.h 中定义。
    hFor:使用编译表达式得到的表达式句柄,但必须由二级函数HFor获得该句柄。
    nModule:该参数必须为变量,不能为常量。该参数返回一个表达式所属的模块。
    myFor:该参数必须为变量,不能为常量。该参数返回一个表达式句柄,该句柄即hFor,可用于表达式的计算。
    Para:该参数必须为变量,不能为常量。该参数返回一个存放表达式自变量的数组指针,可用于输入自变量。
    ParaNum:该参数必须为变量,不能为常量。该参数返回表达式自变量的个数。当ParaNum=-1时表示有0个自变量,当ParaNum=0时表示有1个自变量,当ParaNum=1时表示有2个自变量,依次类推。
    该函数返回true时查询成功,否则返回false。

1.19 判断表达式的自变量是否重新赋值:ParaModify

    bool _stdcall ParaModify( fcKEY ForType,void *vFor);

    ForType:所查询的表达式的类型。只能取Key_IntFor (标识整数表达式)、Key_RealFor (标识实数表达式)、Key_ComplexFor (标识复数表达式)。这三个标识符的值在头文件FORCAL32W.h 中定义。
    vFor:编译表达式时得到的表达式句柄。
    若表达式的自变量重新赋值,该函数返回true,否则返回false。
    该函数不能判断是否对局部变量或全局变量进行了赋值。

    在设计某些程序时,如果在表达式中不对自变量进行重新赋值,可以简化程序的设计,并可加快程序的执行速度。对表达式有此要求者可用该函数进行判断。

1.20 获得表达式中的字符串:GetForStr

    void _stdcall GetForStr(void *hFor,wchar_t *&ForStr,fcINT &StrMin,fcINT &StrMax);

    用法1:

    hFor:从二级函数获得的表达式句柄。不能使用编译表达式得到的表达式句柄。
    ForStr:该参数必须为变量,不能为常量。该参数返回一个字符串指针,表达式中的所有字符串的首地址都可由该指针加一个在[ StrMin~StrMax ]之间的正整数得到。表达式中的所有字符串都是连续存放的。
    StrMin:该参数必须为变量,不能为常量。该参数返回ForStr中可用字符的最小偏移量。StrMin>0。
    StrMax:该参数必须为变量,不能为常量。该参数返回ForStr中可用字符的最大偏移量。StrMax>0。
    注意:只能在二级函数中使用该函数。

    用法2:

    hFor:hFor=NULL。
    ForStr:该参数必须为变量,不能为常量。输入参数为由二级函数HFor获得的表达式句柄。该参数返回一个字符串指针,表达式中的所有字符串的首地址都可由该指针加一个在[
StrMin~StrMax ]之间的正整数得到。表达式中的所有字符串都是连续存放的。
    StrMin:该参数必须为变量,不能为常量。该参数返回ForStr中可用字符的最小偏移量。StrMin>0。
    StrMax:该参数必须为变量,不能为常量。输入参数为表达式类型,只能取1 (标识整数表达式)、2 (标识实数表达式)、3 (标识复数表达式)。该参数返回ForStr中可用字符的最大偏移量。StrMax>0。
    注意:函数工作失败时ForStr和StrMax返回0。

1.21 删除一个表达式:DeleteFor

    void _stdcall DeleteFor ( fcKEY ForType,void *hFor);

    ForType :表达式类型。 只能取Key_IntFor (标识整数表达式)、Key_RealFor (标识实数表达式)、Key_ComplexFor (标识复数表达式)。这三个标识符的值在头文件FORCAL32W.h 中定义。
    hFor
:表达式句柄,该句柄为编译表达式时获得的句柄。

    设有如下表达式定义:

f(x:y,p,static, a1,a2,a3 ,free,b1,b2:c) = ..., free(p), ...;

    当用函数 DeleteFor 删除该表达式时,将设置 静态变量free =1,然后按缺省参数自动调用该表达式,但也可能由于某种原因表达式不可执行(父表达式或该表达式中所调用的二级函数被删除)。任何情况下,在static与free之间的静态变量 a1,a2,a3 标识的对象将被销毁。

    若表达式中没有静态变量free,将不会自动调用该表达式,也不会自动销毁任何静态变量所标识的对象。

    若使用二级函数free(p)对p做了标记,在用函数 DeleteFor 删除该表达式时,将销毁对象p。

    注意1:用函数 DeleteFor 删除一个表达式时,只有用 InsertKeyP 函数注册的对象(用指针标识)才能被静态变量free或函数free所销毁。

    注意2:为了使Forcal在删除表达式时能按正确的次序自动执行表达式,要遵守后编译的表达式要先删除的原则。但即便没有遵循“后进先出”的删除原则,也不会产生灾难性的后果。

1.22 插入一个键:InsertKey

    int _stdcall InsertKey (char *KeyStr,fcINT ByteNum, fcKEY KeyType,void *KeyValue, void (_stdcall *DelKey)(void *),void *&NowKey );

    KeyStr :键的名称。区分大小写,可包含任意字符,包括NULL('\0')。
   
ByteNum :键的长度。 ByteNum>0。
   
KeyType :用户自定义键的类型。KeyType>= FC_Key_User(公有键、普通键) 或者 KeyType<=FC_PrivateKey_User(私有键) 约定用FC_Key_UserFC_PrivateKey_User 保存一些特殊的数据,作为多个函数、线程、动态库等之间联系的通道。FC_Key_UserFC_PrivateKey_User 在头文件FORCAL32W.h 中定义。
   
KeyValue :键值。由用户定义,标识某种数据类型。
    DelKey :删除该键值的函数指针。该函数由用户定义,但由Forcal调用,即: DelKey( KeyValue ); 可将KeyValue删除 。如果不需要Forcal删除该键值,该参数可设为NULL
    NowKey :该参数必须为变量,不能为常量。存在同名同类型的键时,如果 NowKey =0,不更新键值,该参数返回已存在的键值;如果 NowKey !=0,且KeyType<=FC_PrivateKey_User(私有键) ,同时新键和老键的删除函数不相同,不更新键值;其余情况下更新键值。即:

    NowKey =0,不更新键值, NowKey返回已存在的键值。
    NowKey !=0,且 KeyType>=FC_Key_User: 更新键值。
    NowKey !=0,且 KeyType<=FC_PrivateKey_User, 新键和老键的删除函数相同:更新键值。
    NowKey !=0,且 KeyType<=FC_PrivateKey_User, 新键和老键的删除函数不相同:不更新键值 NowKey返回已存在的键值

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

      0:插入成功。
      1:已存在该键。参数
NowKey =0,没有更新键值,由参数 NowKey 返回已存在的键值。或者 NowKey !=0,KeyType<=FC_PrivateKey_User(私有键) ,且新键和老键的删除函数不相同,没有更新键值,参数 NowKey 返回了已存在的键值。
      2:已存在该键。参数
NowKey !=0,当KeyType>=FC_Key_User 时,更新了键值;或者当KeyType<=FC_PrivateKey_User(私有键) ,且新键和老键的删除函数相同时,更新了键值。
      3:键的类型参数
KeyType 非法。
      4:键值类型被唯一指定,删除该键值的函数指针
DelKey 非法,必须使用被唯一指定的函数指针。
      5:内存分配失败。
      6:插入失败,
ByteNum<=0 或其他错误。

    删除函数 InsertKey 插入的键:(1)使用函数 DeleteKey DeletePrivateKey ;(2)用函数 LockKeyType 解锁键时将删除所有指定类型的键值;(3)重新初始化Forcal时由函数 InitForcal 销毁所有键值;(4)释放Forcal时由函数 FreeForcal 销毁所有键值。

1.23 查找一个键:SearchKey

    void * _stdcall SearchKey (char *KeyStr,fcINT ByteNum, fcKEY KeyType);

    KeyStr :键的名称。区分大小写,可包含任意字符,包括NULL('\0')。
   
ByteNum :键的长度。 ByteNum>0。
   
KeyType :用户自定义键的类型。KeyType>= FC_Key_User 或者 KeyType<=FC_PrivateKey_User FC_Key_UserFC_PrivateKey_User 在头文件FORCAL32W.h 中定义。
    如果查找成功,该函数返回键值的指针,否则返回false。

1.24 删除一个键:DeleteKey

    bool _stdcall DeleteKey (char *KeyStr,fcINT ByteNum, fcKEY KeyType);

    KeyStr :键的名称。区分大小写,可包含任意字符,包括NULL('\0')。
   
ByteNum :键的长度。 ByteNum>0。
   
KeyType :用户自定义键的类型。该类型值的最小值为FC_Key_UserFC_Key_User 在头文件FORCAL32W.h 中定义。

    返回值:操作成功返回true,否则返回false。

1.25 删除一个私有键:DeletePrivateKey

    bool _stdcall DeletePrivateKey(char *KeyStr,fcINT ByteNum, fcKEY KeyType,void (_stdcall * DelKey )(void *));

    KeyStr :键的名称。区分大小写,可包含任意字符,包括NULL('\0')。
   
ByteNum :键的长度。 ByteNum>0。
   
KeyType :用户自定义键的类型。该类型值的最大值为FC_PrivateKey_UserFC_PrivateKey_User 在头文件FORCAL32W.h 中定义。
   
DelKey :删除该键值的函数指针。该指针与插入键时用到的函数指针相同,否则不能删除键值。

    返回值:操作成功返回true,否则返回false。

1.26 枚举指定键值类型所对应的所有字符串及键值:EnumKeyTypeValue

    void _stdcall EnumKeyTypeValue( fcKEY KeyType ,char * KeyStr ,int n KeyStr Max,bool (_stdcall *GetKeyTypeValue)(char *,int ,void *));

    KeyType :指定键的类型。KeyType>= FC_Key_User(公有键、普通键) 或者 KeyType<=FC_PrivateKey_User(私有键) FC_Key_UserFC_PrivateKey_User 在头文件FORCAL32W.h 中定义。
   
KeyStr :存放键的名称的缓冲区。如果缓冲区不够用,仅存放键的名称的前面部分字符。
   
n KeyStr Max :存放键的名称的缓冲区的最大长度(n KeyStrMax >=1)。
   
GetKeyTypeValue :回调函数。每当找到指定键的类型对应的键时就调用该函数。该回调函数的说明格式如下:

      bool _stdcall GetKeyTypeValue(char * KeyStr ,int ByteNum,void * KeyValue );
      KeyStr :键的名称。区分大小写,可包含任意字符,包括NULL('\0')。该函数被调用时,将自动在键的名称后面添加一个NULL('\0')。
     
ByteNum :键的长度。同时指出键的名称的完整性。当 ByteNum=nKeyStrMax-1 时,键的名称可能不完整,仅存放了名称的前面部分字符。使用更大的缓冲区可使该函数返回键的完整名称。
     
KeyValue :键值。标识某种数据类型。
      当
GetKeyTypeValue 返回true时,继续枚举其他键值,否则停止枚举。
      注意:不要在该函数中调用除了GetRunErr()、
TestRunErr()和SetRunErr() 三个函数之外的Forcal 输出函数。

1.27 锁定键的类型:LockKeyType

    int _stdcall LockKeyType( fcKEY KeyType,void (_stdcall * DelKey )(void *), void (_stdcall *NullLock)(void) );

    KeyType :被锁定的键的类型。KeyType>= FC_Key_User(公有键、普通键) 或者 KeyType<=FC_PrivateKey_User(私有键) FC_Key_UserFC_PrivateKey_User 在头文件FORCAL32W.h 中定义。
   
DelKey :删除键值的函数指针,用于标识要加锁的键。该函数由用户定义,但由Forcal调用。若 DelKey NULL ,表示解锁指定的键。
   
NullLock :有效的函数指针,该函数仅在加锁或解锁键的类型时被调用一次,一般将该函数设置为空函数。解锁和加锁所用的 NullLock 函数必须相同。
    如果加锁或解锁成功,该函数返回0,否则返回非0值。
    说明:锁定键的类型后,该键只能存储一种数据类型,该数据类型用删除函数标识。如果没有锁定键的类型,则该键可以存储任意多种类型的数据。只有欲加锁的键 没有使用,也没有存储任何类型的数据时,才能将该键加锁;解锁时将删除所有的键值,将键恢复为加锁前未用时的状态。通常在主调程序中锁定的键无需解 锁,Forcal会自动删除键树中的所有数据。在动态库中锁定的键必须解锁,否则将导致不可预知的错误。

1.28 与Forcal交换信息:ExMsgWithForcal

    void * _stdcall ExMsgWithForcal(int Type,void *hMsg,void *&Msg1,void *&Msg2);

    Type :输入参数,信息交换的类型。
   
hMsg :输入参数,信息句柄,其意义取决于 Type
   
Msg1 :该参数必须为变量,不能为常量。输入值及返回值取决于 Type
   
Msg2 :该参数必须为变量,不能为常量。输入值及返回值取决于 Type
    返回值 :NULL表示失败,非0值表示成功。成功时返回值的意义取决于
Type
    说明:与Forcal进行信息交换,向Forcal传送信息或者从Forcal获得信息。信息的类型及意义如下表所示:

Type hMsg Msg1 Msg2 返回值 说明
1 从二级函数获得的表达式句柄

返回表达式类型:
Msg1=1:整数表达式
Msg1=2:实数表达式
Msg1=3:复数表达式

返回表达式句柄 指向表达式名称的字符串指针 得到表达式名称、类型、句柄
2 编译表达式得到的表达式句柄

输入表达式类型:
Msg1=1:整数表达式
Msg1=2:实数表达式
Msg1=3:复数表达式

无意义 指向表达式名称的字符串指针 得到表达式名称
3 从二级函数获得的表达式句柄

返回表达式类型:
Msg1=1:整数表达式
Msg1=2:实数表达式
Msg1=3:复数表达式

返回表达式句柄 表达式模块号 得到表达式模块号、类型、句柄
4 编译表达式得到的表达式句柄

输入表达式类型:
Msg1=1:整数表达式
Msg1=2:实数表达式
Msg1=3:复数表达式

无意义 表达式模块号 得到表达式模块号
5 无意义 无意义 无意义 无意义 未使用
6 无意义 无意义 无意义 无意义 未使用
7 字符串指针 无意义 无意义 指向整数常量的指针 得到Forcal中的整数常量
8 字符串指针 无意义 无意义 指向实数常量的指针 得到Forcal中的实数常量
9 字符串指针 无意义 无意义 指向复数常量的指针 得到Forcal中的复数常量
10 模块号 无意义 无意义 模块中的表达式数目 得到模块中的表达式数目
11 无意义 无意义 无意义 无意义 未使用
12 当hMsg非0时编译未说明的模块变量 无意义 无意义 无意义 设置是否编译未说明的模块变量,参考[注1]
13 无意义 无意义 无意义 无意义 未使用
14 无意义 无意义 无意义 无意义 未使用
15 从二级函数获得的表达式句柄 Msg1!=0:二级函数将返回一个临时对象
Msg1==0:二级函数不返回临时对象
无意义 返回非0表示操作成功,只有在oo函数中试图返回临时对象时才会操作成功 在整数或实数二级函数中通知Forcal,二级函数是否返回临时对象[注2] 。二级函数默认将返回一个值,即Msg1=0。
16 从二级函数获得的表达式句柄 Msg1=0或指向临时对象的指针(fcIFOR *) 二级函数存放参数的数组指针,即二级函数第二个参数 返回非0表示操作成功 在二级函数内首次调用时Msg1=0,通知Forcal做好准备。Msg1!=0时保存二级函数申请的临时对象[注2] ,以便oo函数可自动销毁它。
17 从二级函数获得的表达式句柄 指向临时对象的指针(fcIFOR *) 无意义 返回非0表示操作成功 销毁在当前二级函数中已通过Type=16注册保存但不想再用的临时对象[注2][注3]

    [注1] :在用函数 IntCom RealCom ComplexCom 编译表达式时,缺省情况下,所有用到的模块变量必须预先定义。可用函数 ExMsgWithForcal Type=12, hMsg非0)通知编译器使用未定义的模块变量(若一个标识符没有定义,且不是常量,将被解释为模块变量);也可用函数 ExMsgWithForcal Type=12,hMsg为0)通知编译器取消这种设置。无论表达式编译是否成功,将恢复缺省设置,即:所有用到的模块变量必须预先声明。

    [注2] :临时对象都是直接或间接由函数 InsertKeyP 创建的,且都用指针标识。

    [注3] : 如果在二级函数设计中通过Type=16注册保存了临时对象,当打算不再使用该对象时,可用Type=17销毁该对象,Forcal将调用合适的函数销毁 该临时对象,并取消原先的注册标识。当然你可以自行销毁该对象,但Forcal还将进行销毁该对象的尝试;或者你可以等待垃圾收集器回收该对象。

1.29 插入一个指针键:InsertKeyP

    int _stdcall InsertKeyP(char *KeyStr,fcINT ByteNum,fcKEY KeyType,void *KeyValue,void (_stdcall *DelKey)(void *),FcOperator oo,void (_stdcall *SignKey)(void *),unsigned int mode,void *&NowKey);

    KeyStr :键的名称。区分大小写,可包含任意字符,包括NULL('\0')。通常键的名称是一个指针(标识一个对象)的地址,例如对于指针 void *me KeyStr (char *)&me
   
ByteNum :键的长度。 ByteNum>0。 如果键的名称是一个指针,在32位平台上, ByteNum=4
   
KeyType :用户自定义键的类型。KeyType>= FC_Key_User(公有键、普通键) 或者 KeyType<=FC_PrivateKey_User(私有键) 。约定用FC_Key_UserFC_PrivateKey_User 保存一些特殊的数据,作为多个函数、线程、动态库等之间联系的通道。FC_Key_UserFC_PrivateKey_User 在头文件FORCAL32W.h 中定义。
   
KeyValue :键值。由用户定义,标识某种数据类型。
   
DelKey :删除该键值的函数指针。该函数由用户定义,但由Forcal调用,即: DelKey(KeyValue); 可将KeyValue删除。如果不需要Forcal删除该键值,该参数可设为NULL
    oo
FcOperator 类型的函数指针,用于对象(用指针标识)的运算符重载,必须提供该参数。参考[注1]
   
SignKey :标记子键值(对象)的函数指针,所有标记过的子对象都是有效(可达)对象,不会被垃圾收集器所回收。该函数由用户定义,但由Forcal调用,即: SignKey(KeyValue); KeyValue若包含另外的对象,则调用该函数可对其他对象做标记,应在函数 SignKey 中对每一个对象调用函数SignGoodObj 做标记。若 KeyValue 不能包含子对象,该参数设为NULL 。参考[注2]
   
mode :该参数必须为变量,不能为常量。该参数指出键值(对象)的属性。 mode 共32位,从左往右,第1位必须为0;第2位表示该对象是否会包含子对象(当第2位为1且提供了函数 SignKey 时, SignKey 将被自动调用;该位的值可由二级函数SaveSubObj 重新设置);其他位必须为0。
   
NowKey :该参数必须为变量,不能为常量。存在同名同类型的键时,如果 NowKey =0,不更新键值,该参数返回已存在的键值;如果 NowKey !=0,且KeyType<=FC_PrivateKey_User(私有键) ,同时新键和老键的删除函数不相同,不更新键值;其余情况下更新键值。即:

    NowKey=0,不更新键值,NowKey返回已存在的键值。
    NowKey !=0,且 KeyType>=FC_Key_User: 更新键值。
    NowKey !=0,且 KeyType<=FC_PrivateKey_User, 新键和老键的删除函数相同:更新键值。
    NowKey !=0,且 KeyType<=FC_PrivateKey_User, 新键和老键的删除函数不相同:不更新键值, NowKey返回已存在的键值。

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

      0:插入成功。
      1:已存在该键。参数
NowKey =0,没有更新键值,由参数 NowKey 返回已存在的键值。或者 NowKey !=0,KeyType<=FC_PrivateKey_User(私有键) ,且新键和老键的删除函数不相同,没有更新键值,参数 NowKey 返回了已存在的键值。
      2:已存在该键。参数
NowKey !=0,当KeyType>=FC_Key_User 时,更新了键值;或者当KeyType<=FC_PrivateKey_User(私有键) ,且新键和老键的删除函数相同时,更新了键值。
      3:键的类型参数
KeyType 非法。
      4:键值类型被唯一指定,删除该键值的函数指针
DelKey 非法,必须使用被唯一指定的函数指针。
      5:内存分配失败。
      6:插入失败,其他类型的指针键已经存在,或者
ByteNum<=0 ,或者其他错误。

    删除函数 InsertKeyP 插入的指针键:(1)使用函数 DeleteKey DeletePrivateKey ;(2)用函数 LockKeyType 解锁键时将删除所有指定类型的键值;(3)系统自动销毁oo函数中的临时对象(临时对象都是用指针标识的)时,将设置 theOperator =0 销毁该指针键;(4)垃圾收集器GC 将直接调用函数 DelKey 删除该指针键;(5)重新初始化Forcal时由函数 InitForcal 销毁所有键值;(6)释放Forcal时由函数 FreeForcal 销毁所有键值。

    说明:

    (1)只有用 InsertKeyP 函数注册的对象(用指针标识)才能在oo函数中进行运算符重载。

    (2)只有用 InsertKeyP 函数注册的对象(用指针标识)才能被垃圾收集器回收。

    (3)用函数 DeleteFor 删除一个表达式时,只有用 InsertKeyP 函数注册的对象(用指针标识)才能被静态变量free或函数free所销毁。

    设有如下表达式定义:

f(x:y,p,static, a1,a2,a3 ,free,b1,b2:c) = ..., free(p), ...;

    当用函数 DeleteFor 删除该表达式时,将设置 静态变量free =1,然后按缺省参数自动调用该表达式,但也可能由于某种原因表达式不可执行(父表达式或该表达式中所调用的二级函数被删除)。任何情况下,在static与free之间的静态变量 a1,a2,a3 标识的对象将被销毁。

    若表达式中没有静态变量free,将不会自动调用该表达式,也不会自动销毁任何静态变量所标识的对象。

    若使用二级函数free(p)对p做了标记,在用函数 DeleteFor 删除该表达式时,将销毁对象p。

    [注1] : 在Forcal脚本中,函数oo{..., a+b, ...}中的运算符将被重载(该函数不可嵌套使用),运算符的第一操作数(例如a+b中的a)将被看作是一个指针(指向一个对象),Forcal在运算时 将查找该指针的运算符重载函数,如果找到就调用该函数,否则将返回一个运行错误。有些重载运算符会返回一个临时对象,该临时对象在生命期结束时自动销毁。

    运算符重载函数 FcOperator 函数格式如下:

//m指出数组Para的参数个数(也即操作数的个数,0表示1个,1表示2个,以此类推),数组Para的类型取决于iForType:iForType=1为整数fcIFOR类型;iForType=2为实数double类型。
//hFor为调用该函数的表达式句柄(与编译表达式时返回的表达式句柄并不相同 ,如果有意义,与二级函数中的表达式句柄相同)。
//reVal为指向返回值的指针(必须返回一个值),指针的类型取决于iForType:iForType=1为整数fcIFOR类型;iForType=2为实数double类型。
//theOperator指出运算符的类型或操作类型:+、-、*、/、^、... ...。
//返回值=0:未定义;返回值=1:临时对象;返回值=2:当前对象;返回值=3:逻辑值;返回值=其他值:未定义。
int (_stdcall *FcOperator)(fcINT m,void *Para,void *hFor,void *reVal,int iForType,int theOperator);

int _stdcall oo(fcINT m,void *Para,void *hFor,void *reVal,int iForType,int theOperator)
{
   
//... ...
    switch(theOperator)
    {
    case 0:   
//销毁临时对象
       
//... ...
    case 1:    //将临时对象转为一般对象
       
//... ...
    case 2:    //将一般对象转为临时对象
       
//... ...
    case 4:    //重载运算符+
       
//... ...
    case 5:   
//重载运算符-
       
//... ...
    ... ...
    }
}

    Forcal中可重载的运算符、函数及操作如下表:

theOperator 运算符 功  能 参数个数m 默认返回值 说  明
0   销毁临时对象 0 无意义 该临时对象的生命期已结束,需要销毁该对象;通常用函数 DeleteKey DeletePrivateKey 销毁该对象;也可以将该对象放到缓冲区中暂存,以提高运行效率。注意不要使用 hFor 参数,该参数无意义。
1 to(p) 将临时对象转为一般对象 0 当前对象 临时对象指由oo函数自动销毁的对象,否则为一般对象。当在脚本中使用函数to(p)时,将收到该通知。
2 oofree(p) 将一般对象转为临时对象 0 当前对象 当在脚本中使用函数oofree(p)时,将收到该通知。
3 未使用        
4 + 1 临时对象 双目运算符。
5 - 1 临时对象 双目运算符。
6 * 1 临时对象 双目运算符。
7 / 1 临时对象 双目运算符。
8 % 或 ^ 求模 或 乘方 1 临时对象 双目运算符。运算符%用在整数表达式中;运算符^用在实数表达式中。
9 - 0 临时对象 单目运算符。
10 ++ 前置自增 ++i 0 当前对象 单目运算符。
11 ++ 后置自增 i++ 0 临时对象 单目运算符。 申请临时变量,将输入参数赋值给临时变量,然后将输入参数增1,返回临时变量。
12 -- 前置自减 --i 0 当前对象 单目运算符。
13 -- 后置自减 i-- 0 临时对象 单目运算符。 申请临时变量,将输入参数赋值给临时变量,然后将输入参数减1,返回临时变量。
14 > 大于 1 逻辑值 双目运算符。
15 >= 大于等于 1 逻辑值 双目运算符。
16 < 小于 1 逻辑值 双目运算符。
17 <= 小于等于 1 逻辑值 双目运算符。
18 == 等于 1 逻辑值 双目运算符。
19 != 不等于 1 逻辑值 双目运算符。
20 & 1 逻辑值 双目运算符。
21 | 1 逻辑值 双目运算符。
22 ! 0 逻辑值 单目运算符。
30 内部使用 在o函数中调用外部函数      
31 o{...} 重载函数 不确定 被忽略 该函数一般用于获得对象信息,至少需要一个参数,第一个参数即要操作的对象。可接受任意多个参数。
由于返回值被忽略,若函数o{...}要返回临时对象,必须用函数
ExMsgWithForcal (Type为15)通知Forcal。
32 oset{...} 重载函数 不确定 被忽略 该函数一般用于对象赋值,至少需要一个参数,第一个参数即要赋值的对象。可接受任意多个参数。
由于返回值被忽略,若函数oset{...}要返回临时对象,必须用函数
ExMsgWithForcal (Type为15)通知Forcal。
33 oget{...} 重载函数 不确定 被忽略 该函数一般用于获得对象的值,至少需要一个参数,第一个参数即要操作的对象。可接受任意多个参数。
由于返回值被忽略,若函数oget{...}要返回临时对象,必须用函数
ExMsgWithForcal (Type为15)通知Forcal。

    [注2] :标记子键值(对象)的函数 SignKey 格式如下:

void _stdcall SignKey(void *me)
{
    ...
    SignGoodObj(p);
    //p是me的子对象,用函数 SignGoodObj标记该子对象
    ...
}

1.30 垃圾收集时标记一个指针键(对象):SignGoodObj

    bool _stdcall SignGoodObj(void *me);

    通知Forcal的垃圾收集器,me是一个可达的(有效的)对象。标记成功返回true

1.31 垃圾收集:GC

    int _stdcall GC(int n);

    立即启动Forcal垃圾收集器,n设为0,返回值无意义。Forcal使用标记清除算法进行垃圾回收。只有用 InsertKeyP 函数注册的对象(用指针标识)才能被垃圾收集器回收。

    在Forcal中,一个对象用一个指针标识,在32位平台上,一个指针是存放在一个数(整数、实数或复数)的前4个字节中,此时,我们也称这个数为指向该 对象的指针。若Forcal系统中的静态变量、模块变量、全局变量以及正在运行的表达式的数据区(自变量、动态变量及数据堆栈)中存在一个数指向一个对象 时,该对象是有效的,否则视为垃圾对象,会被垃圾收集器所回收。

    一个对象的子对象能否被垃圾收集器回收,可参考 InsertKeyP 函数的 SignKey 参数和mode 参数的说明。所有用函数 SignKey 标记过的对象都是有效(可达)对象,不会被垃圾收集器所回收。

    由于只要有一个指针(直接或间接)指向某对象,该对象就不会被垃圾收集器回收,故若要确保立即销毁某对象,应使用delete之类的专用函数,而不要依赖垃圾收集器。

2 简单计算 [返回页首 ]

2.1 使用FORCAL进行简单的整数计算

    1、用InitForcal () 初始化Forcal;
    2、用
IntCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,fcIFOR *&Para,fcINT &ErrBegin,fcINT &ErrEnd) 编译表达式,模块号nModule根据实际情况设置;
    3、用
IntCal(void *hFor,fcIFOR *d) 计算表达式;
    4、用FreeForcal() 释放Forcal。

2 .2 使用FORCAL进行简单的实数计算

    1、用InitForcal () 初始化Forcal;
    2、用
RealCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,double *&Para,fcINT &ErrBegin,fcINT &ErrEnd) 编译表达式,模块号nModule根据实际情况设置;
    3、用
RealCal(void *hFor,double *d) 计算表达式;
    4、用FreeForcal() 释放Forcal。

2.3 使用FORCAL进行简单的复数计算

    1、用InitForcal () 初始化Forcal;
    2、用
ComplexCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,_complex *&Para,fcINT &ErrBegin,fcINT &ErrEnd) 编译表达式,模块号nModule根据实际情况设置;
    3、用
ComplexCal(void *hFor,_complex *d) 计算表达式;
    4、用FreeForcal() 释放Forcal。

2.4 使用FORCAL进行简单的实数、整数和复数计算

    1、用InitForcal () 初始化Forcal。

    2、编译表达式

      用 IntCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,fcIFOR *&Para,fcINT &ErrBegin,fcINT &ErrEnd) 编译整数表达式,模块号nModule根据实际情况设置;
      用
RealCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,double *&Para,fcINT &ErrBegin,fcINT &ErrEnd) 编译实数表达式,模块号nModule根据实际情况设置;
      用
ComplexCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,_complex *&Para,fcINT &ErrBegin,fcINT &ErrEnd) 编译复数表达式,模块号nModule根据实际情况设置;

    3、计算表达式

      用 IntCal(void *hFor,fcIFOR *d) 计算整数表达式;
      用
RealCal(void *hFor,double *d) 计算实数表达式;
      用
ComplexCal(void *hFor,_complex *d) 计算复数表达式;

    4、用 FreeForcal() 释放Forcal。

3 FORCAL二级函数设计 [返回页首 ]

    以设计实数二级函数为例进行说明,复数、整数的二级函数设计与此类似。

    二级函数的一般形式是:

      double _stdcall Fun2Name(fcINT n,double *d,void *hFor);

    相应地,在表达式中二级函数的使用形式是

      Fun2Name(X1,X2,... ...,Xn)

    数组d中依次存放各个自变量 X1,X2,... ...,Xn;整数n指出自变量的个数,其大小为自变量的个数减1。

     hFor 是由Forcal传送过来的调用该二级函数的表达式的句柄,该句柄与编译表达式所获得的句柄不同。由该句柄可以获得更多的信息。

    以下是二级函数设计中可能用到的FORCAL输出函数及注意事项:

    1、用 GetForStr (...)函数获得表达式中的字符串。
    2、 用GetFor (...)函数获得各个表达式并进行计算。
    3、用 TestRunErr(void)测试是否有 运行错误。由于FORCAL允许另一个线程修改运行时的出错状态,以便退出FORCAL运行,因此在二级函数设计中,在可能导致无限循环的循环体内,要使用TestRunErr()函数检测运行错误,如果检测到任何错误,就退出该二级函数。
    4、用
SetRunErr (...)设置外部函数的运行错误。
    5、Forcal不鼓励在二级函数中抛出异常,二级函数中产生的异常最好在本函数内检测,然后转换成Forcal运行错误。如果在二级函数中抛出了异常, 通常主调程序需要重新初始化Forcal。实际上,如果进行混合语言编程,二级函数中抛出异常可能导致不可预知的错误。

4 FORCAL的基本用法 [返回页首 ]

    尽管FORCAL表达式的用法可以非常灵活,但以下两种用法可能是最基本的。

4.1 动态使用字符串表达式

    程序在运行过程中,动态地使用字符串表达式并进行计算。例如根据需要计算字符串数学表达式的值,或者执行一定的命令等。

    在这种方法中,对于一种特定的运算,仅在需要的时候使用FORCAL,而其他的代码要用C/C++或FORTRAN等高级语言来写。

    用这种方法得到的数值计算程序,其执行速度约为C/C++或FORTRAN执行速度的50%左右。但程序一经生成,即可脱离高级语言编译器独立运行,象使用Matlab和Mathematics一样方便。

4.2 按次序依次执行表达式进行运算

    这是用FORCAL进行编程的一种方式。程序文件中的表达式用分隔符(通常用分号“;”)分隔,按某种次序依次编译各个表达式,编译成功后,按编译次序依次执行各个表达式。

    无论哪种使用方式,在编译表达式前后和计算表达式前后都要检查FORCAL运行错误。

    Forcal始终记着编译过的表达式,这使得同名的表达式将不能再被编译,除非你释放了该表达式所占据的空间。可以用 DeleteFor (...)函数释放一个表达式所占据的空间。如果使用初始化函数InitForcal(),将连同注册的二级函数、常量、申请的数组、注册的所有自定义数据等一并删除。

5 Forcal软件组成与使用   [返回页首 ]

    Forcal由核心库Forcal32W.dll和一组Forcal扩展动态库组成。实际应用中可以单独使用Forcal32W.dll,也可以使用Forcal32W.dll与各种扩展库的组合。

5.1 仅使用Forcal32W.dll

    程序在运行过程中,动态地使用字符串表达式并进行计算。例如根据需要计算字符串数学表达式的值,或者执行一定的命令等。

    在这种方法中,对于一种特定的运算,仅在需要的时候使用FORCAL,而其他的代码要用C/C++或FORTRAN等高级语言来写。

    用这种方法得到的数值计算程序,其执行速度约为C/C++或FORTRAN执行速度的50%左右。但程序一经生成,即可脱离高级语言编译器独立运行,像使用Matlab和Mathematics一样方便。

5.2 使用Forcal扩展数据类型

    需要加载FcData32W,该库是Forcal数据扩展动态库。在FcData中可以创建使用任意的数据类型,但FcData中定义的直接对数据进行计 算或操作的函数较少,FcData主要向Forcal提供更加丰富的数据类型,对FcData数据的计算或操作更多地依赖其他动态库的函数进行。因而,在 加载FcData32W的同时,很可能还要加载其他一些对FcData数据操作的动态库。例如:FcString32W或XSLSF32W等等。

5.3 使用Forcal模块化编译功能

    需要加载MForcalW。MForcalW对Forcal源程序进行模块化编译,能够编译运行具有固定格式的源程序(字符串表达式),源程序中可以使用C++风格的注释。

5.4 使用Forcal模块并使用Forcal扩展数据类型

    同时加载MForcalW和FcData32W,这两个库相互独立,因而先加载哪个都可以。一般还要加载其他一些对FcData数据操作的动态库。例如:FcString32W或XSLSF32W等等。

5.5 使用Forcal用于某种特殊目的

    举例来说,如果绘制OpenGL图形,须加载OpenFcGl32W,这是一个基于OpenGL的进行图形绘制的动态库。如果进行数值计算,须加载XSLSF32W,这是一个数值计算动态库。以此类推。

    一般用于某种特殊目的的动态库需要FcData32W的支持,而为了方便对源代码的模块化编译则需要MForcalW的支持,因而一般也少不了这两个动态库。

5.6 仍不能满足要求

    需要自己编写Forcal扩展动态库。也不一定局限于动态库的形式,对Forcal进行功能扩展可以在主程序或任意的模块中进行。只要获得一个Forcal32W.dll句柄,就可以对Forcal进行任意的功能扩展。

    对Forcal的功能扩展没有任何限制,FcData32W、MForcalW等所有这些动态库都是通过Forcal32W.dll的输出函数实现的。 Forcal对功能扩展提供了很好的支持,以充分满足各种实际需要。对Forcal的功能扩展不会降低Forcal的编译和运行效率。发挥您的想象 力,Forcal会使您的程序获得非凡的功能。

6 用FORCAL保存和检索数据   [返回页首 ]

    Forcal用多键值字符串键树保存和检索数据信息,具有存储效率高、查询速度快的优点。用户可将自定义的数据信息保存到该键树中,并与Forcal融为 一体。用户可通过InsertKey(...)、SearchKey(...)、DeleteKey(...)、 DeletePrivateKey (...)等函数往键树中插入、查询和删除数据信息。

分享到:
评论

相关推荐

    forcal编程软件

    这个是forcal进行编程的工具,对于需要此程序的人,希望能提供帮助

    VC Forcal7调用例子.rar

    VC Forcal7调用例子,请在此输入表达式!一次只计算一个表达式!  可在多行中输入表达式。  如果有自变量,只进行编译,但将保留编译结果,自定义的函数随时可以调用。  重新初始化将清除以前的编译结果。  ...

    开放式计算程序OpenFC

     OpenFC是一个开放式的数值计算程序,由Forcal32.dll和MForcal32.dll提供支持。  OpenFC能够编译运行具有固定格式的源程序(字符串表达式),源程序中可以使用C++风格的注释。源程序中可以使用的运算符有+、-、*、...

    FORCAL数值计算扩展动态库FcIMSL V1.0测试版.pdf

    FORCAL数值计算扩展动态库FcIMSL V1.0测试版.pdf

    Forcal数据库应用

    让Forcal的控制台应用程序能够读取数据库中的表达式字符串并计算,你只要双击\ForcalConsole\Forcal数据库应用\ForcalConsole.exe文件,就可以完成创建数据库,读取数据库中的表达式字符串并运算的功能了。...

    FORCAL V7.0 字符表达式编译运行库

    内容索引:VC/C++源码,控件相关,Forcal,编译 Forcal是一个对字符表达式进行编译计算的动态链接库,具有数值计算、关系运算、逻辑运算、字符处理、流程控制、函数调用等许多的可编程功能。它的部分开发文档是由C++...

    通用的数学表达式编译计算动态库 V5.1

    令人欣喜的是,现在有了FORCAL.DLL,您可以在软件中自由地添加各种数值计算功能,享受到一劳永逸之乐趣。 该动态库支持实数、复数和整数三种类型的数学表达式,这三种表达式可以单独使用,也可同时使用,在同时使用...

    数学计算系统.rar

    数学和工程计算平台,采用forcal语言和内核,内置有丰富的范例可供参考,可广泛应用于数学建模,工程设计与计算,作图,程式设计等等,计算速度快而准确,让你解决问题不再感觉困难。

Global site tag (gtag.js) - Google Analytics