如何在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例程
在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.1 用指针标识对象的特点
与C++中标识对象的指针类似。动态地申请和销毁对象。对象是全局性的,只要获得了该对象的指针,就可以操作该对象。每次申请,都会返回一个对象,对象是用指针来区别的,而指针永远不会重复。
可以设置一个缓冲区,暂时存储最近访问的对象,以提高运行效率。
在脚本中,若程序设计不合理,可导致对象暴增。例如,在一个循环中申请对象但并不销毁它。
2.2 用字符串标识对象的特点
动态地申请和销毁对象。对象是全局性的,只要知道标识该对象的字符串,就可以操作该对象。对象是用字符串来区别的,若两次用同一个字符串申请对象,则第二次申请将失败。
设置一个缓冲区,暂时存储最近访问的对象,难以提高运行效率。故通常不设置缓冲区。
在脚本中,若程序设计不合理,也不会使对象暴增。例如,在一个循环中申请对象但并不销毁它,但仅第一次申请成功,以后的申请都是失败的。
不宜在大程序中使用字符串标识的对象。例如,字符串"aa"只能标识某种类型的对象中的一个,若在多个函数中使用,将相互干扰。
本例子将要用到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;
}
};
程序中实现了如下函数:
(1)NewArray(m,x1,x2,...,xn):实数函数
该函数申请一维双精度实数数组,返回该对象的句柄。数组长度为m,可存储m个实数,可用x1,x2,...,xn对数组赋初值,初值个数应小于或等于数组的长度,多余的初值将被忽略。
该函数可返回如下运行错误代码:
1:参数太少,至少需要一个参数。
2:数组长度非法。
3:内存错误。
(2)DeleteArray(p):实数函数
销毁数组p。p是由函数NewArray返回的对象指针。返回值无意义。
(3)SetArray(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:数组元素地址非法。
该例子加载了一个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;
}
程序中实现了如下函数:
(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)SetArray("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:数组元素地址非法。
该例子加载了一个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
最近更新: <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y年%m月%d日" startspan -->2010年08月22日<!--webbot bot="Timestamp" i-checksum="1279" endspan -->