FORCAL32.DLL V8.0 编程指南

欢迎访问 Forcal数学软件

FORCAL32.DLL V8.0 编程指南

目 录

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

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

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

在以下的说明中,fcINT被定义为长整型long,即:

typedef long fcINT;

1 输出函数 [返回页首]

1.1 版本信息函数

const char * _stdcall ForcalVer(void);

1.2 初始化FORCAL

bool _stdcall InitForcal(void);

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

1.3 释放FORCAL

void _stdcall FreeForcal(void);

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

1.4 获得FORCAL运行错误

void _stdcall GetRunErr(int &ErrType,char *&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:返回出错表达式的句柄,该句柄即编译表达式时获得的句柄。

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

1.5 测试FORCAL运行错误

int _stdcall TestRunErr(void);

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

1.6 设置FORCAL运行错误

void _stdcall SetRunErr(int ErrType,char *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(stdTestRunErr)函数测试是否出现过运行错误,如果还没有出现,可以进行设置,否则,不能进行设置。

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

1.7 编译实数表达式

int _stdcall RealCom(char *ForStr,fcINT 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:因检测到运行错误而退出!

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

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

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

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

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

1.8计算实数表达式的值

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

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

1.9 编译整数表达式

int _stdcall IntCom(char *ForStr,fcINT nModule,void *&hFor,fcINT &nPara,fcINT *&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计算整数表达式的值

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

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

1.11 编译复数表达式

int _stdcall ComplexCom(char *ForStr,fcINT 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计算复数表达式的值

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

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

1.13 锁定一个模块

bool _stdcall LockModule(fcINT 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 设置外部二级函数

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

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

fcINT IntFun(fcINT m,fcINT *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标准函数调用方式)。

1.15 设置常量

int _stdcall SetConst(fcINT ConstType,char *ConstName,void *ConstValue);

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

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

例如:

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

1.16 删除常量或二级函数

void _stdcall DeleteConstOrFunction(fcINT Type,char *Name);

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

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

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

用法1:

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

用法2:

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

1.18 获得表达式信息

bool _stdcall GetFor(char *ForName,fcINT ForType,void *hFor,fcINT &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的值在头文件FORCAL32.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的值在头文件FORCAL32.h中定义。
hFor:使用编译表达式得到的表达式句柄,但必须由二级函数HFor获得该句柄。
nModule:该参数必须为变量,不能为常量。该参数返回一个表达式所属的模块。
myFor:该参数必须为变量,不能为常量。该参数返回一个表达式句柄,该句柄即hFor,可用于表达式的计算。
Para:该参数必须为变量,不能为常量。该参数返回一个存放表达式自变量的数组指针,可用于输入自变量。
ParaNum:该参数必须为变量,不能为常量。该参数返回表达式自变量的个数。当ParaNum=-1时表示有0个自变量,当ParaNum=0时表示有1个自变量,当ParaNum=1时表示有2个自变量,依次类推。
该函数返回true时查询成功,否则返回false。

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

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

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

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

1.20 获得表达式中的字符串

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

用法1:

hFor:从二级函数获得的表达式句柄。不能使用编译表达式得到的表达式句柄。
ForStr:该参数必须为变量,不能为常量。该参数返回一个字符串指针,表达式中的所有字符串的首地址都可由该指针加一个整数得到。表达式中的所有字符串都是连续存放的。
StrMax
:该参数必须为变量,不能为常量。该参数返回表达式中所有字符串的总长度。
注意:只能在二级函数中使用该函数。

用法2:

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

1.21 删除一个表达式

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

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

说明:设有如下表达式定义:

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

当Forcal删除该表达式时,将设置静态变量free=1,然后按缺省参数自动调用该表达式。若由于某种原因表达式不可执行(父表达式或该表达式中所调用的二级函数被删除),则检查是否有预先设置的回调函数DeleteStaticToFree,若有则调用之,调用时将在static与free之间的静态变量a1,a2,a3传送到该函数。

若表达式中没有静态变量free,将不会自动调用该表达式,也不会调用回调函数DeleteStaticToFree

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

1.22 插入一个键

int _stdcall InsertKey(char *KeyStr,fcINT ByteNum,fcINT 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在头文件FORCAL7.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或其他错误。

1.23 查找一个键

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

KeyStr:键的名称。区分大小写,可包含任意字符,包括NULL('/0')。
ByteNum:键的长度。ByteNum>0。

KeyType:用户自定义键的类型。KeyType>=FC_Key_User 或者 KeyType<=FC_PrivateKey_UserFC_Key_UserFC_PrivateKey_User在头文件FORCAL7.h中定义。
如果查找成功,该函数返回键值的指针,否则返回false。

1.24 删除一个键

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

KeyStr:键的名称。区分大小写,可包含任意字符,包括NULL('/0')。
ByteNum:键的长度。ByteNum>0。

KeyType:用户自定义键的类型。该类型值的最小值为FC_Key_UserFC_Key_User在头文件FORCAL7.h中定义。

1.25 删除一个私有键

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

KeyStr:键的名称。区分大小写,可包含任意字符,包括NULL('/0')。
ByteNum:键的长度。ByteNum>0。

KeyType:用户自定义键的类型。该类型值的最大值为FC_PrivateKey_UserFC_PrivateKey_User在头文件FORCAL7.h中定义。
DelKey:删除该键值的函数指针。该指针与插入键时用到的函数指针相同,否则不能删除键值。

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

void _stdcall EnumKeyTypeValue(fcINT KeyType,char *KeyStr,int nKeyStrMax,bool (_stdcall *GetKeyTypeValue)(char *,int ,void *));

KeyType:指定键的类型。KeyType>=FC_Key_User(公有键、普通键) 或者 KeyType<=FC_PrivateKey_User(私有键)FC_Key_UserFC_PrivateKey_User在头文件FORCAL7.h中定义。
KeyStr
:存放键的名称的缓冲区。如果缓冲区不够用,仅存放键的名称的前面部分字符。
nKeyStrMax:存放键的名称的缓冲区的最大长度(nKeyStrMax
>=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 锁定键的类型

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

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

1.28 与Forcal交换信息

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

Type:输入参数,信息交换的类型。
hMsg:输入参数,信息句柄,其意义取决于Type

Msg1:该参数必须为变量,不能为常量。输入值及返回值取决于Type

Msg2:该参数必须为变量,不能为常量。输入值及返回值取决于Type

返回值:NULL表示失败,非0值表示成功。成功时返回值的意义取决于Type

说明:与Forcal进行信息交换,向Forcal传送信息或者从Forcal获得信息。信息的类型及意义如下表所示:

TypehMsgMsg1Msg2返回值说明
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回调函数指针:用于删除在static与free之间的静态变量所标识的数据无意义无意义无意义向Forcal传送一个回调函数DeleteStaticToFree,参考[注1]
6无意义无意义无意义无意义删除向Forcal传送的回调函数DeleteStaticToFree
7字符串指针无意义无意义指向整数常量的指针得到Forcal中的整数常量
8字符串指针无意义无意义指向实数常量的指针得到Forcal中的实数常量
9字符串指针无意义无意义指向复数常量的指针得到Forcal中的复数常量
10模块号无意义无意义模块中的表达式数目得到模块中的表达式数目

注1:向Forcal传送的回调函数定义如下:

//删除在static与free之间的静态变量所标识的数据
void _stdcall DeleteStaticToFree(int DataType,void *Data,fcINT DataMax)
{
... ...;
}

DataType:数据类型。DataType=1表示整数数据,DataType=2表示实数数据,DataType=3表示整数数据。
Data:数据指针。数据类型取决于DataTypeDataType=1时为(fcINT *)数据,DataType=2时为(double *)数据,DataType=3时为(_complex *
)数据。
DataMax:有效数据个数。

设有如下表达式定义:

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

当用函数DeleteFor删除该表达式时,将设置静态变量free=1,然后按缺省参数自动调用该表达式。若由于某种原因表达式不可执行(父表达式或该表达式中所调用的二级函数被删除),则检查是否有预先设置的回调函数DeleteStaticToFree,若有则调用之,调用时将在static与free之间的静态变量a1,a2,a3传送到该函数。

若表达式中没有静态变量free,将不会自动调用该表达式,也不会调用回调函数DeleteStaticToFree。

在回调函数DeleteStaticToFree中允许调用DeleteKeyDeletePrivateKey等函数。

2 简单计算 [返回页首]

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

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

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

1、用InitForcal()初始化Forcal;
2、用RealCom(char *ForStr,fcINT 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(char *ForStr,fcINT 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(char *ForStr,fcINT nModule,void *&hFor,fcINT &nPara,fcINT *&Para,fcINT &ErrBegin,fcINT &ErrEnd)编译整数表达式,模块号nModule根据实际情况设置;
RealCom(char *ForStr,fcINT nModule,void *&hFor,fcINT &nPara,double *&Para,fcINT &ErrBegin,fcINT &ErrEnd)
编译实数表达式,模块号nModule根据实际情况设置;
ComplexCom(char *ForStr,fcINT nModule,void *&hFor,fcINT &nPara,_complex *&Para,fcINT &ErrBegin,fcINT &ErrEnd)编译复数表达式,模块号nModule根据实际情况设置;

3、计算表达式

IntCal(void *hFor,fcINT *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(...)设置外部函数的运行错误。

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由核心库Forcal32.dll和一组Forcal扩展动态库组成。实际应用中可以单独使用Forcal32.dll,也可以使用Forcal32.dll与各种扩展库的组合。

5.1、仅使用Forcal32.dll

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

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

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

5.2、使用Forcal扩展数据类型

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

5.3、使用Forcal模块化编译功能

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

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

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

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

举例来说,如果绘制OpenGL图形,须加载OpenFcGl32,这是一个基于OpenGL的进行图形绘制的动态库。如果进行微积分运算,须加载CALCULAS32,这是一个微积分动态库。以此类推。

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

5.6、仍不能满足要求

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

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

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

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


版权所有© Forcal数学软件 2002-2008,保留所有权利
E-mail:
forcal@sina.com
QQ:630715621
最近更新: <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y年%m月%d日" startspan -->2009年06月01日<!--webbot bot="Timestamp" i-checksum="1281" endspan -->

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值