欢迎访问 Forcal程序设计

如何在FORCAL中添加对象

目 录

1 在Forcal中添加对象的一般步骤 2 如何选择对象的标识 2.1 用指针标识对象的特点 2.2 用字符串标识对象的特点 3 将要用到的一些函数 4 设计自己的对象MyArray | 5 用指针标识对象 5.1 对象操作函数 5.2 源代码 6 用字符串标识对象 6.1 对象操作函数 6.2 源代码

开发者在软件中添加一些对象，然后通过脚本操作这些对象，是许多程序员的梦想。在Forcal中添加对象，然后通过Forcal脚本操作这些对象，是很容易的一件事。看完本文后你可能忍不住要尝试一番，只要你用过像C/C++、Delphi等具有指针的语言。你不需要是一个资深的程序员，一个普通的编程者即可。本文将展示Forcal的强大的可扩充性和易扩充性，不过这是很容易实现的。

本文将使用VS2008 C++进行演示，编译时请将活动解决方案配置为“Release”，这些例子很容易移植到任何一个C++编译器中。 这些都是完整的例子，复制下来直接编译运行即可。为了减少代码，这些例子都是控制台应用程序，简单地加以改写，将它应用到实用的Windows程序中去是不难的。

为了更好地理解本文的例子，请参考：循序渐进Forcal例程

1 在Forcal中添加对象的一般步骤

在Forcal脚本中，对象可以用指针或字符串进行标识。

通过Forcal32W.dll的输出函数添加对象是最基本的，主要步骤如下：

> （1）设计自己的对象MyObj，可以是任意复杂的。

> （2）设计对象操作函数：

> 设计Forcal二级函数NewMyObj()，用于申请一个MyObj对象。每次申请的对象的指针，都要用函数InsertKey()保存到Forcal，其键的类型自然是MyObjKeyType 。
> 设计Forcal二级函数DelMyObj()，用于销毁一个MyObj对象。只能用函数DeletePrivateKey()销毁。
> 设计操作对象MyObj的其他Forcal二级函数，在操作前，必须用函数SearchKey()验证对象指针是否有效。

> （3）初始化时，用函数LockKeyType()选择并加锁一个私有键MyObjKeyType，并将所有的对象操作函数注册到Forcal。对于私有键，只有自己专用的函数才可以删除它；一个键加锁后，只能存储一种数据类型。

> （4）程序退出时，注销向Forcal注册的二级函数，用函数LockKeyType()解锁键MyObjKeyType并销毁所有MyObj对象。在主程序中这些工作可以省略。

2 如何选择对象的标识

2.1 用指针标识对象的特点

与C++中标识对象的指针类似。动态地申请和销毁对象。对象是全局性的，只要获得了该对象的指针，就可以操作该对象。每次申请，都会返回一个对象，对象是用指针来区别的，而指针永远不会重复。

可以设置一个缓冲区，暂时存储最近访问的对象，以提高运行效率。

在脚本中，若程序设计不合理，可导致对象暴增。例如，在一个循环中申请对象但并不销毁它。

2.2 用字符串标识对象的特点

动态地申请和销毁对象。对象是全局性的，只要知道标识该对象的字符串，就可以操作该对象。对象是用字符串来区别的，若两次用同一个字符串申请对象，则第二次申请将失败。

设置一个缓冲区，暂时存储最近访问的对象，难以提高运行效率。故通常不设置缓冲区。

在脚本中，若程序设计不合理，也不会使对象暴增。例如，在一个循环中申请对象但并不销毁它，但仅第一次申请成功，以后的申请都是失败的。

不宜在大程序中使用字符串标识的对象。例如，字符串"aa"只能标识某种类型的对象中的一个，若在多个函数中使用，将相互干扰。

3 将要用到的一些函数 [返回页首]

本例子将要用到Forcal的几个输出函数，这里仅列出简单说明，详细说明请参考loadforcal.htm文件，相信大家能找到这些函数的说明，看不懂也不要紧，可以通过后面的代码了解这些函数的具体应用。

1）初始化FORCAL：bool _stdcall InitForcal(void);

2） 释放FORCAL：void _stdcall FreeForcal(void);

3）测试FORCAL运行错误：int _stdcall TestRunErr(void);

如果检测到错误，我们就没有必要进行一些耗时较长的操作了。在向Forcal发送一个错误时，也需要检查有没有运行错误，若有，就没有必要发送了。

4） 获得FORCAL运行错误：void _stdcall GetRunErr(int &ErrType,wchar_t *&FunName,int &FunCode,int &ForType,void *&ForHandle);

FORCAL在运行时，将记录出现的第一个运行错误。通常在编译表达式前后和执行表达式前后使用该函数。使用该函数后，FORCAL将恢复为无错状态。

5）设置FORCAL运行错误：void _stdcall SetRunErr(int ErrType,wchar_t *FunName,int FunCode,int ForType,void *ForHandle);

有任何运行错误，都要通过该函数告诉Forcal。例如本例中，如果我们没有得到我们期望的对象，就调用该函数。

6）设置外部二级函数：int _stdcall SetFunction(fcKEY FunType,wchar_t *FunName,void *Fun,fcINT ParaNum);

这是一个重要函数。我们注册的对象的所有操作都要通过一些函数来实现，这些函数要注册到Forcal中才能使用。这些函数就是通过 SetFunction 注册的。

7） 编译实数表达式：int _stdcall RealCom(wchar_t *ForStr,fcVOID nModule,void *&hFor,fcINT &nPara,double *&Para,fcINT &ErrBegin,fcINT &ErrEnd);

编译成功，将返回一个句柄 hFor，可通过该句柄计算表达式的值。

8） 计算实数表达式：double _stdcall RealCal(void *hFor,double *d);

使用编译表达式时返回的句柄 hFor，数组d存放自变量。

9）获得表达式中的字符串：void _stdcall GetForStr(void *hFor,wchar_t *&ForStr,fcINT &StrMin,fcINT &StrMax);

由于对象可用字符串进行标识，因而将用到该函数。

10）查找一个键：void * _stdcall SearchKey(char *KeyStr,fcINT ByteNum,fcKEY KeyType);

我们申请的对象注册到了Forcal中，在对一个对象操作前，需要用该函数判断对象是否存在。

11）插入一个键：int _stdcall InsertKey(char *KeyStr,fcINT ByteNum,fcKEY KeyType,void *KeyValue,void (_stdcall *DelKey)(void *),void *&NowKey);

该函数可以将新的对象注册到Forcal中。

12）删除一个私有键：void _stdcall DeletePrivateKey(char *KeyStr,fcINT ByteNum,fcKEY KeyType,void (_stdcall *DelKey)(void *));

该函数用于销毁一个对象。该函数太酷了，其他线程无法通过该函数销毁我们自己申请的对象。

13）锁定键的类型：int _stdcall LockKeyType(fcKEY KeyType,void (_stdcall *DelKey)(void *),void (_stdcall *NullLock)(void));

要想用一种Forcal键值专门标识我们的对象类型，必须用该函数锁定该键值。

4 设计自己的对象MyArray [返回页首]

对象可以是任意复杂的，但为了简单，我们将定义一个一维数组对象。

> //定义自己的对象MyArray，可以是任意复杂的对象
> class MyArray
> {
> public:
> double *Array;
> int max;
> MyArray(){Array=NULL; max=0;}
> ~MyArray()
> {
> if(Array) delete[] Array;
> }
> };

5 用指针标识对象 [返回页首]

5.1 对象操作函数 [返回页首]

程序中实现了如下函数：

（1）NewArray(m,x1,x2,...,xn)：实数函数

该函数申请一维双精度实数数组，返回该对象的句柄。数组长度为m，可存储m个实数，可用x1,x2,...,xn对数组赋初值，初值个数应小于或等于数组的长度，多余的初值将被忽略。

该函数可返回如下运行错误代码：

1：参数太少，至少需要一个参数。
2：数组长度非法。
3：内存错误。

（2）DeleteArray(p)：实数函数

销毁数组p。p是由函数 NewArray 返回的对象指针。返回值无意义。

（3）Set Array(p,i:x1,x2,... ...)：实数函数

在数组p中，自第i个单元开始，依次存放 x1,x2,... ...。仍返回数组p。

该函数可返回如下运行错误代码：

1：参数太少，至少需要2个参数。
2：该数组对象不存在。
3：数组元素地址非法。

（4）GetArray(p,i:&x1,&x2,... ...)：实数函数

在数组p中，将自第i个单元开始的元素。依次存放到变量 x1,x2,... ...中。仍返回数组p。

该函数可返回如下运行错误代码：

1：参数太少，至少需要2个参数。
2：该数组对象不存在。
3：数组元素地址非法。

5.2 源代码 [返回页首]

该例子加载了一个Forcal扩展动态库QuitFc32W.dll，该库中启动了一个线程，专门用于监视Forcal运行。在任意可接受输入的窗口，按 Ctrl+Alt+Q(q) 键可以退出Forcal运行时的无限循环。

该例子测试了如下函数：测试(:p,a,b,c)= p=NewArray[3,11,22,33], GetArray[p,0,&a,&b,&c], a+b+c

可修改该测试字符串表达式进行其他测试。

源代码：

> #include <windows.h>
> #include <cmath>
> #include <iostream>
> #include <iomanip>
> #include "forcal32w.h" //使用Forcal必须的头文件
> using namespace std;
> HINSTANCE hForcal=NULL; //动态库Forcal32W.dll的句柄；
> HINSTANCE hQuitFc=NULL; //动态库QuitFc32W.dll的句柄；
> //动态库Forcal32W.dll的输出函数;
> fcInitForcal InitForcal;
> fcFreeForcal FreeForcal;
> fcRealCom RealCom;
> fcRealCal RealCal;
> fcSetFunction SetFunction;
> fcTestRunErr TestRunErr;
> fcGetRunErr GetRunErr;
> fcSetRunErr SetRunErr;
> fcSearchKey SearchKey;
> fcInsertKey InsertKey;
> fcDeletePrivateKey DeletePrivateKey;
> fcLockKeyType LockKeyType;
> //Forcal扩展动态库的输出函数;
> fcFcDll32W pFcDll32W;
> //////////////////////
> class MyArray //定义自己的数组
> {
> public:
> double *Array;
> int max;
> MyArray(){Array=NULL; max=0;}
> ~MyArray()
> {
> if(Array) delete[] Array;
> }
> };
> fcKEY KeyMyArray=FC_PrivateKey_User-100; //标识对象MyArray的私有键
> void _stdcall NullLock(void ) //加锁键值时用到的空函数，由Forcal自动调用该函数
> {
> }
> void _stdcall DeleteMyArray(void *me) //该函数删除me，me是一个MyArray对象指针，由Forcal自动调用该函数
> {
> delete (MyArray *)me;
> }
> //////////////////////
> //实数二级函数定义；
> double _stdcall rfc_NewArray(fcINT m,double *xx,void *vFor) //申请一个数组
> {
> static wchar_t ErrName[]=L"NewArray";
> MyArray *pMyArray;
> void *NowKey;
> int i,j;
> double d=0.0;
> if(m<0) //至少需要1个参数
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,1,0,vFor); return 0.0;
> }
> pMyArray=new MyArray;
> if(pMyArray)
> {
> pMyArray->max=(int)xx[0];
> if(pMyArray->max<1)
> {
> delete pMyArray;
> if(TestRunErr()==0) SetRunErr(2,ErrName,2,0,vFor); return 0.0;
> }
> pMyArray->Array=new double[pMyArray->max];
> if((!pMyArray->Array))
> {
> delete pMyArray;
> if(TestRunErr()==0) SetRunErr(2,ErrName,3,0,vFor); return 0.0;
> }
> for(i=0,j=1;i<pMyArray->max;i++,j++)
> {
> if(j>m) break;
> pMyArray->Array[i]=xx[j];
> }
> NowKey=0;
> if(!InsertKey((char *)&pMyArray,sizeof(fcVOID),KeyMyArray,pMyArray,DeleteMyArray,NowKey)) //将MyArray对象保存到Forcal
> {
> *(fcVOID *)&d=(fcVOID)pMyArray; return d;
> }
> if(TestRunErr()==0) SetRunErr(2,ErrName,3,0,vFor);
> delete pMyArray;
> }
> return 0;
> }
> double _stdcall rfc_DeleteArray(fcINT m,double *xx,void *vFor) //销毁一个MyArray对象
> {
> DeletePrivateKey((char *)xx,sizeof(fcVOID),KeyMyArray,DeleteMyArray);
> return 0.0;
> }
> double _stdcall rfc_SetArray(fcINT m,double *xx,void *vFor) //给MyArray对象赋值
> {
> static wchar_t ErrName[]=L"SetArray";
> MyArray *pMyArray;
> int i,j;
> if(m<1)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,1,0,vFor); return 0.0;
> }
> pMyArray=(MyArray *)SearchKey((char *)xx,sizeof(fcVOID),KeyMyArray); //查找是否存在MyArray对象
> if(!pMyArray)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,2,0,vFor); return 0.0;
> }
> i=(int)xx[1];
> if(i<0 || i>=pMyArray->max)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,3,0,vFor); return 0.0;
> }
> for(j=2;i<pMyArray->max;i++,j++)
> {
> if(j>m) break;
> pMyArray->Array[i]=xx[j];
> }
> return xx[0];
> }
> double _stdcall rfc_GetArray(fcINT m,double *xx,void *vFor) //获得MyArray对象的值
> {
> static wchar_t ErrName[]=L"GetArray";
> MyArray *pMyArray;
> int i,j;
> if(m<1)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,1,0,vFor); return 0.0;
> }
> pMyArray=(MyArray *)SearchKey((char *)xx,sizeof(fcVOID),KeyMyArray); //查找是否存在MyArray对象
> if(!pMyArray)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,2,0,vFor); return 0.0;
> }
> i=(int)xx[1];
> if(i<0 || i>=pMyArray->max)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,3,0,vFor); return 0.0;
> }
> for(j=2;i<pMyArray->max;i++,j++)
> {
> if(j>m) break;
> xx[j]=pMyArray->Array[i];
> }
> return xx[0];
> }
> /////////////////////////////////////////////////
> void myFreeForcal(void) //释放Forcal；
> {
> if(hQuitFc) //释放QuitFc
> {
> pFcDll32W(hForcal,false,0);
> }
> LockKeyType(KeyMyArray,0,NullLock); //解锁键KeyMyArray并销毁所有MyArray对象
> FreeForcal(); //释放Forcal申请的空间；
> FreeLibrary(hForcal); //释放动态库；
> }
> bool myInitForcal(void) //初始化Forcal；
> {
> hForcal=LoadLibrary(L"Forcal32W.dll"); //加载动态库Forcal32W.dll；
> if(!hForcal)
> {
> cout<<"找不到Forcal32W.dll！请将该库放到WINDOWS的搜索路径内！";
> return false;
> }
> //以下几个语句获取Forcal32W.dll中所调用函数的地址；
> InitForcal=(fcInitForcal) GetProcAddress(hForcal,"InitForcal");
> FreeForcal=(fcFreeForcal) GetProcAddress(hForcal,"FreeForcal");
> RealCom=(fcRealCom) GetProcAddress(hForcal,"RealCom");
> RealCal=(fcRealCal) GetProcAddress(hForcal,"RealCal");
> SetFunction=(fcSetFunction) GetProcAddress(hForcal,"SetFunction");
> TestRunErr=(fcTestRunErr) GetProcAddress(hForcal,"TestRunErr");
> GetRunErr=(fcGetRunErr) GetProcAddress(hForcal,"GetRunErr");
> SetRunErr=(fcSetRunErr) GetProcAddress(hForcal,"SetRunErr");
> SearchKey=(fcSearchKey) GetProcAddress(hForcal,"SearchKey");
> InsertKey=(fcInsertKey) GetProcAddress(hForcal,"InsertKey");
> DeletePrivateKey=(fcDeletePrivateKey) GetProcAddress(hForcal,"DeletePrivateKey");
> LockKeyType=(fcLockKeyType) GetProcAddress(hForcal,"LockKeyType");
> if( !InitForcal||!FreeForcal||!RealCom||!RealCal||!SetFunction
> ||!TestRunErr||!GetRunErr||!SetRunErr||!SearchKey||!InsertKey||!DeletePrivateKey||!LockKeyType)
> {
> cout<<"无效的动态库函数！"<<endl;
> FreeLibrary(hForcal); //释放动态库Forcal32W.dll；
> hForcal=NULL;
> return false;
> }
> InitForcal(); //初始化Forcal32W.dll；
> LockKeyType(KeyMyArray,DeleteMyArray,NullLock); //加锁键KeyMyArray。若不能确定是否加锁成功，使用下面的程序段
> /*for(KeyMyArray = FC_PrivateKey_User-1; KeyMyArray>-10000000; KeyMyArray--)
> {
> if(!LockKeyType(KeyMyArray,DeleteMyArray,NullLock)) break; //加锁键KeyMyArray
> }
> if(KeyMyArray==-10000000) //无法加锁一个键
> {
> FreeForcal(); //释放Forcal申请的空间；
> FreeLibrary(hForcal); //释放动态库Forcal32W.dll；
> hForcal=NULL;
> return false;
> }*/
> hQuitFc=LoadLibrary(L"QuitFc32W.dll"); //加载动态库QuitFc32W.dll；
> if(hQuitFc)
> {
> //获得Forcal扩展动态库输出函数的地址；
> pFcDll32W=(fcFcDll32W) GetProcAddress(hQuitFc,"FcDll32W");
> if(pFcDll32W)
> {
> if(!pFcDll32W(hForcal,true,0)) //初始化QuitFc；
> {
> FreeLibrary(hQuitFc); //释放动态库QuitFc；
> hQuitFc=NULL;
> }
> }
> else
> {
> FreeLibrary(hQuitFc); //释放动态库QuitFc；
> hQuitFc=NULL;
> }
> }
> SetFunction(Key_RealFunction,L"NewArray",rfc_NewArray,-2); //设置实数二级函数；
> SetFunction(Key_RealFunction,L"DeleteArray",rfc_DeleteArray,0); //设置实数二级函数；
> SetFunction(Key_RealFunction,L"SetArray",rfc_SetArray,-2); //设置实数二级函数；
> SetFunction(Key_RealFunction,L"GetArray",rfc_GetArray,-2); //设置实数二级函数；
> return true;
> }
> void main(void)
> {
> void *vFor; //表达式句柄；
> fcINT nPara; //存放表达式的自变量个数；
> double *pPara; //存放输入自变量的数组指针；
> fcINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置；
> int ErrCode; //错误代码；
> int ErrType; //运行错误类型；
> wchar_t *FunName; //出错函数名；
> int ForType; //运行出错的表达式类型；
> void *ForHandle; //运行出错的表达式句柄；
> wchar_t ForStr[]=L"测试(:p,a,b,c)= p=NewArray[3,11,22,33], GetArray[p,0,&a,&b,&c], a+b+c"; //字符串表达式；
> if(!myInitForcal()) return; //初始化Forcal；
> GetRunErr(ErrType,FunName,ErrCode,ForType,ForHandle); //设置运行错误为无错状态；
> wcout.imbue(locale("chs")); //设置输出的locale为中文
> vFor=0;
> ErrCode=RealCom(ForStr,0,vFor,nPara,pPara,ErrBegin,ErrEnd);//编译实数表达式；
> if(ErrCode)
> {
> cout<<"表达式有错误！错误代码："<<ErrCode<<endl;
> }
> else
> {
> cout<<RealCal(vFor,pPara)<<endl; //计算实数表达式的值；
> GetRunErr(ErrType,FunName,ErrCode,ForType,ForHandle); //检查运行错误；
> if(ErrType) wcout<<L"出现运行错误！错误类型："<<ErrType<<L"；出错函数名："<<FunName<<L"；错误代码："<<ErrCode<<endl;
> }
> myFreeForcal(); //释放Forcal；
> }

6 用字符串标识对象 [返回页首]

6.1 对象操作函数 [返回页首]

程序中实现了如下函数：

（1）NewArray("aa",m,x1,x2,...,xn)：实数函数

该函数申请一维双精度实数数组"aa"，仍返回"aa"。数组长度为m，可存储m个实数，可用x1,x2,...,xn对数组赋初值，初值个数应小于或等于数组的长度，多余的初值将被忽略。

该函数可返回如下运行错误代码：

1：参数太少，至少需要2个参数。
2：需要用字符串参数指出数组名称。
3：数组长度非法。
4：内存错误。
5：该数组已存在。

（2）DeleteArray("aa")：实数函数

销毁数组"aa"。返回值无意义。

（3）Set Array("aa",i:x1,x2,... ...)：实数函数

在数组"aa"中，自第i个单元开始，依次存放 x1,x2,... ...。仍返回数组"aa"。

该函数可返回如下运行错误代码：

1：参数太少，至少需要2个参数。
2：需要用字符串参数指出数组名称。
3：该数组对象不存在。
4：数组元素地址非法。

（4）GetArray("aa",i:&x1,&x2,... ...)：实数函数

在数组"aa"中，将自第i个单元开始的元素。依次存放到变量 x1,x2,... ...中。仍返回数组"aa"。

该函数可返回如下运行错误代码：

1：参数太少，至少需要2个参数。
2：需要用字符串参数指出数组名称。
3：该数组对象不存在。
4：数组元素地址非法。

6.2 源代码 [返回页首]

该例子加载了一个Forcal扩展动态库QuitFc32W.dll，该库中启动了一个线程，专门用于监视Forcal运行。在任意可接受输入的窗口，按 Ctrl+Alt+Q(q) 键可以退出Forcal运行时的无限循环。

该例子测试了如下函数：测试(:a,b,c)= NewArray["aa",3,11,22,33], GetArray["aa",0,&a,&b,&c], a+b+c

可修改该测试字符串表达式进行其他测试。

源代码：

> #include <windows.h>
> #include <cmath>
> #include <iostream>
> #include <iomanip>
> #include "forcal32w.h" //使用Forcal必须的头文件
> using namespace std;
> HINSTANCE hForcal=NULL; //动态库Forcal32W.dll的句柄；
> HINSTANCE hQuitFc=NULL; //动态库QuitFc32W.dll的句柄；
> //动态库Forcal32W.dll的输出函数;
> fcInitForcal InitForcal;
> fcFreeForcal FreeForcal;
> fcRealCom RealCom;
> fcRealCal RealCal;
> fcSetFunction SetFunction;
> fcTestRunErr TestRunErr;
> fcGetRunErr GetRunErr;
> fcSetRunErr SetRunErr;
> fcGetForStr GetForStr;
> fcSearchKey SearchKey;
> fcInsertKey InsertKey;
> fcDeletePrivateKey DeletePrivateKey;
> fcLockKeyType LockKeyType;
> //Forcal扩展动态库的输出函数;
> fcFcDll32W pFcDll32W;
> //////////////////////
> class MyArray //定义自己的数组
> {
> public:
> double *Array;
> int max;
> MyArray(){Array=NULL; max=0;}
> ~MyArray()
> {
> if(Array) delete[] Array;
> }
> };
> fcKEY KeyMyArray=FC_PrivateKey_User-100; //标识对象MyArray的私有键
> void _stdcall NullLock(void ) //加锁键值时用到的空函数，由Forcal自动调用该函数
> {
> }
> void _stdcall DeleteMyArray(void *me) //该函数删除me，me是一个MyArray对象指针，由Forcal自动调用该函数
> {
> delete (MyArray *)me;
> }
> //////////////////////
> //实数二级函数定义；
> double _stdcall rfc_NewArray(fcINT m,double *xx,void *vFor) //申请一个数组
> {
> static wchar_t ErrName[]=L"NewArray";
> wchar_t *pStr;
> fcINT k,StrMin,StrMax;
> MyArray *pMyArray;
> void *NowKey;
> int i,j;
> if(m<1) //至少需要2个参数
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,1,0,vFor); return 0.0;
> }
> GetForStr(vFor,pStr,StrMin,StrMax); //获得Forcal字符串
> k=(fcINT)xx[0];
> if(k<StrMin||k>StrMax) //需用字符串指出对象名
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,2,0,vFor); return 0.0;
> }
> pMyArray=new MyArray;
> if(pMyArray)
> {
> pMyArray->max=(int)xx[1];
> if(pMyArray->max<1)
> {
> delete pMyArray;
> if(TestRunErr()==0) SetRunErr(2,ErrName,3,0,vFor); return 0.0;
> }
> pMyArray->Array=new double[pMyArray->max];
> if((!pMyArray->Array))
> {
> delete pMyArray;
> if(TestRunErr()==0) SetRunErr(2,ErrName,4,0,vFor); return 0.0;
> }
> for(i=0,j=2;i<pMyArray->max;i++,j++)
> {
> if(j>m) break;
> pMyArray->Array[i]=xx[j];
> }
> NowKey=0;
> i=InsertKey((char *)&pStr[k],wcslen(&pStr[k])*2,KeyMyArray,pMyArray,DeleteMyArray,NowKey); //将MyArray对象保存到Forcal
> if(!i) //操作成功
> {
> return xx[0];
> }
> else if(i==1) //已存在该数组
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,5,0,vFor);
> }
> else
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,4,0,vFor);
> }
> delete pMyArray;
> }
> return 0;
> }
> double _stdcall rfc_DeleteArray(fcINT m,double *xx,void *vFor) //销毁一个MyArray对象
> {
> wchar_t *pStr;
> fcINT k,StrMin,StrMax;
> GetForStr(vFor,pStr,StrMin,StrMax); //获得Forcal字符串
> k=(fcINT)xx[0];
> if(k>=StrMin && k<=StrMax) //需用字符串指出对象名
> {
> DeletePrivateKey((char *)&pStr[k],wcslen(&pStr[k])*2,KeyMyArray,DeleteMyArray);
> }
> return 0.0;
> }
> double _stdcall rfc_SetArray(fcINT m,double *xx,void *vFor) //给MyArray对象赋值
> {
> static wchar_t ErrName[]=L"SetArray";
> wchar_t *pStr;
> fcINT k,StrMin,StrMax;
> MyArray *pMyArray;
> int i,j;
> if(m<1)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,1,0,vFor); return 0.0;
> }
> GetForStr(vFor,pStr,StrMin,StrMax); //获得Forcal字符串
> k=(fcINT)xx[0];
> if(k<StrMin||k>StrMax) //需用字符串指出对象名
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,2,0,vFor); return 0.0;
> }
> pMyArray=(MyArray *)SearchKey((char *)&pStr[k],wcslen(&pStr[k])*2,KeyMyArray); //查找是否存在MyArray对象
> if(!pMyArray)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,3,0,vFor); return 0.0;
> }
> i=(int)xx[1];
> if(i<0 || i>=pMyArray->max)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,4,0,vFor); return 0.0;
> }
> for(j=2;i<pMyArray->max;i++,j++)
> {
> if(j>m) break;
> pMyArray->Array[i]=xx[j];
> }
> return xx[0];
> }
> double _stdcall rfc_GetArray(fcINT m,double *xx,void *vFor) //获得MyArray对象的值
> {
> static wchar_t ErrName[]=L"GetArray";
> wchar_t *pStr;
> fcINT k,StrMin,StrMax;
> MyArray *pMyArray;
> int i,j;
> if(m<1)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,1,0,vFor); return 0.0;
> }
> GetForStr(vFor,pStr,StrMin,StrMax); //获得Forcal字符串
> k=(fcINT)xx[0];
> if(k<StrMin||k>StrMax) //需用字符串指出对象名
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,2,0,vFor); return 0.0;
> }
> pMyArray=(MyArray *)SearchKey((char *)&pStr[k],wcslen(&pStr[k])*2,KeyMyArray); //查找是否存在MyArray对象
> if(!pMyArray)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,3,0,vFor); return 0.0;
> }
> i=(int)xx[1];
> if(i<0 || i>=pMyArray->max)
> {
> if(TestRunErr()==0) SetRunErr(2,ErrName,4,0,vFor); return 0.0;
> }
> for(j=2;i<pMyArray->max;i++,j++)
> {
> if(j>m) break;
> xx[j]=pMyArray->Array[i];
> }
> return xx[0];
> }
> /////////////////////////////////////////////////
> void myFreeForcal(void) //释放Forcal；
> {
> if(hQuitFc) //释放QuitFc
> {
> pFcDll32W(hForcal,false,0);
> }
> LockKeyType(KeyMyArray,0,NullLock); //解锁键KeyMyArray并销毁所有MyArray对象
> FreeForcal(); //释放Forcal申请的空间；
> FreeLibrary(hForcal); //释放动态库；
> }
> bool myInitForcal(void) //初始化Forcal；
> {
> hForcal=LoadLibrary(L"Forcal32W.dll"); //加载动态库Forcal32W.dll；
> if(!hForcal)
> {
> cout<<"找不到Forcal32W.dll！请将该库放到WINDOWS的搜索路径内！";
> return false;
> }
> //以下几个语句获取Forcal32W.dll中所调用函数的地址；
> InitForcal=(fcInitForcal) GetProcAddress(hForcal,"InitForcal");
> FreeForcal=(fcFreeForcal) GetProcAddress(hForcal,"FreeForcal");
> RealCom=(fcRealCom) GetProcAddress(hForcal,"RealCom");
> RealCal=(fcRealCal) GetProcAddress(hForcal,"RealCal");
> SetFunction=(fcSetFunction) GetProcAddress(hForcal,"SetFunction");
> TestRunErr=(fcTestRunErr) GetProcAddress(hForcal,"TestRunErr");
> GetRunErr=(fcGetRunErr) GetProcAddress(hForcal,"GetRunErr");
> SetRunErr=(fcSetRunErr) GetProcAddress(hForcal,"SetRunErr");
> GetForStr=(fcGetForStr) GetProcAddress(hForcal,"GetForStr");
> SearchKey=(fcSearchKey) GetProcAddress(hForcal,"SearchKey");
> InsertKey=(fcInsertKey) GetProcAddress(hForcal,"InsertKey");
> DeletePrivateKey=(fcDeletePrivateKey) GetProcAddress(hForcal,"DeletePrivateKey");
> LockKeyType=(fcLockKeyType) GetProcAddress(hForcal,"LockKeyType");
> if( !InitForcal||!FreeForcal||!RealCom||!RealCal||!SetFunction
> ||!TestRunErr||!GetRunErr||!SetRunErr||!GetForStr||!SearchKey||!InsertKey||!DeletePrivateKey||!LockKeyType)
> {
> cout<<"无效的动态库函数！"<<endl;
> FreeLibrary(hForcal); //释放动态库Forcal32W.dll；
> hForcal=NULL;
> return false;
> }
> InitForcal(); //初始化Forcal32W.dll；
> LockKeyType(KeyMyArray,DeleteMyArray,NullLock); //加锁键KeyMyArray。若不能确定是否加锁成功，使用下面的程序段
> /*for(KeyMyArray = FC_PrivateKey_User-1; KeyMyArray>-10000000; KeyMyArray--)
> {
> if(!LockKeyType(KeyMyArray,DeleteMyArray,NullLock)) break; //加锁键KeyMyArray
> }
> if(KeyMyArray==-10000000) //无法加锁一个键
> {
> FreeForcal(); //释放Forcal申请的空间；
> FreeLibrary(hForcal); //释放动态库Forcal32W.dll；
> hForcal=NULL;
> return false;
> }*/
> hQuitFc=LoadLibrary(L"QuitFc32W.dll"); //加载动态库QuitFc32W.dll；
> if(hQuitFc)
> {
> //获得Forcal扩展动态库输出函数的地址；
> pFcDll32W=(fcFcDll32W) GetProcAddress(hQuitFc,"FcDll32W");
> if(pFcDll32W)
> {
> if(!pFcDll32W(hForcal,true,0)) //初始化QuitFc；
> {
> FreeLibrary(hQuitFc); //释放动态库QuitFc；
> hQuitFc=NULL;
> }
> }
> else
> {
> FreeLibrary(hQuitFc); //释放动态库QuitFc；
> hQuitFc=NULL;
> }
> }
> SetFunction(Key_RealFunction,L"NewArray",rfc_NewArray,-2); //设置实数二级函数；
> SetFunction(Key_RealFunction,L"DeleteArray",rfc_DeleteArray,0); //设置实数二级函数；
> SetFunction(Key_RealFunction,L"SetArray",rfc_SetArray,-2); //设置实数二级函数；
> SetFunction(Key_RealFunction,L"GetArray",rfc_GetArray,-2); //设置实数二级函数；
> return true;
> }
> void main(void)
> {
> void *vFor; //表达式句柄；
> fcINT nPara; //存放表达式的自变量个数；
> double *pPara; //存放输入自变量的数组指针；
> fcINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置；
> int ErrCode; //错误代码；
> int ErrType; //运行错误类型；
> wchar_t *FunName; //出错函数名；
> int ForType; //运行出错的表达式类型；
> void *ForHandle; //运行出错的表达式句柄；
> wchar_t ForStr[]=L"测试(:a,b,c)= NewArray[\"aa\",3,11,22,33], GetArray[\"aa\",0,&a,&b,&c], a+b+c"; //字符串表达式；
> if(!myInitForcal()) return; //初始化Forcal；
> GetRunErr(ErrType,FunName,ErrCode,ForType,ForHandle); //设置运行错误为无错状态；
> wcout.imbue(locale("chs")); //设置输出的locale为中文
> vFor=0;
> ErrCode=RealCom(ForStr,0,vFor,nPara,pPara,ErrBegin,ErrEnd);//编译实数表达式；
> if(ErrCode)
> {
> cout<<"表达式有错误！错误代码："<<ErrCode<<endl;
> }
> else
> {
> cout<<RealCal(vFor,pPara)<<endl; //计算实数表达式的值；
> GetRunErr(ErrType,FunName,ErrCode,ForType,ForHandle); //检查运行错误；
> if(ErrType) wcout<<L"出现运行错误！错误类型："<<ErrType<<L"；出错函数名："<<FunName<<L"；错误代码："<<ErrCode<<endl;
> }
> myFreeForcal(); //释放Forcal；
> }

版权所有© Forcal程序设计 2002-2010，保留所有权利
E-mail: forcal@sina.com QQ：630715621
最近更新: 2010年08月22日