如何在FORCAL中添加对象

欢迎访问 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)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:数组元素地址非法。

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)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:数组元素地址非法。

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
最近更新: <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y年%m月%d日" startspan -->2010年08月22日<!--webbot bot="Timestamp" i-checksum="1279" endspan -->

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值