欢迎访问 Forcal程序设计

通用FORCAL脚本系统GForcal（General Forcal DLL）

目 录

1 什么是GForcal
2 GForcal中的函数
2.1 GForcal中的输出函数 | 函数虽多，但常用的也许只有几个。
2.2 Forcal脚本中可用的函数 | 在主程序和Forcal脚本之间用于数据交换的函数。
3 例子
例子3.1～3.5的C#示例代码 | 感谢刘圆圆先生（mgenx@live.com）为例子3.1～3.5编写了C#代码，下载：http://www.forcal.net/xiazai/forcal9/forcal9code.rar
3.1 使用缺省方式执行模块 | 演示如何按缺省方式编译运行一段Forcal源代码，并获得运行结果。
3.2 使用自定义方式执行模块 | 演示如何按自定义方式编译运行一段Forcal源代码，并输出运行结果。
3.3 使用Forcal脚本中的全局函数 | 演示如何使用Forcal中定义的全局函数。这样可方便地与Forcal系统中的静态变量、模块变量以及全局变量进行交互，这些变量可以是任意的对象。
3.4 操作Forcal系统中的数组对象 | 演示如何操作Forcal系统中的数组对象，同时也演示如何加载使用Forcal扩展库。
3.5 通过GForcal的输出函数交互数据 | 演示如何通过GForcal的输出函数与Forcal系统交互数据。
3.6 操作来自Forcal扩展库中的任意对象 | 只要知道对象的标识和对象的定义，就可以方便地进行操作。

1 什么是GForcal [返回页首]

GForcal32W.dll是一个通用的Forcal脚本系统（简称GForcal）。GForcal可看作应用程序与Forcal之间的一个接口，但GForcal简化了Forcal脚本的使用。

GForcal至少需要三个dll的支持：Forcal核心库Forcal32W.dll、Forcal模块化编译运行库MForcal32W.dll和Forcal数据类型扩展动态库FcData32W.dll。这三个支持库的位置比较灵活：（1）与GForcal32W.dll放在一起；（2）放在GForcal32W.dll所在文件夹的子文件夹“FcDll”中；（3）放在Windows搜索目录。

通过GForcal，可动态地加载和卸载任意多个Forcal扩展库，灵活地使用Forcal脚本系统。

GForcal支持在多线程中使用Forcal的功能。GForcal内置了一个Forcal运行监视器，以方便用户从无限循环中退出。

任意程序加载GForcal后，可以：动态定义函数，供程序使用；动态对指定的对象进行操作，并获得结果；无限的功能扩展。

2 GForcal中的函数 [返回页首]

2.1 GForcal中的 输出函数

函 数 | 说 明 | 来 源 | 是否需要UseForcal
InitGForcal | 初始化GForcal。 | GForcal | 否
FreeGForcal | 释放GForcal。 | GForcal | 否
GetInstance | 得到Forcal32W.dll、MForcal32W.dll和FcData32W.dll的句柄。 | GForcal | 否
GetProcAddr | 通过动态库句柄和函数名获得动态库的输出函数。 | GForcal | 否
LoadDll | 加载Forcal扩展动态库。 | GForcal | 否
FreeDll | 释放Forcal扩展动态库。 | GForcal | 否
ReInitGFC | 重新初始化GForcal。 | GForcal | 否
GetRunErr | 获得FORCAL运行错误 | Forcal | 否
TestRunErr | 测试FORCAL运行错误 | Forcal | 否
SetRunErr | 设置FORCAL运行错误 | Forcal | 否
UseForcal | 申请进入或退出Forcal工作区 | MForcal | －
ComModule | 编译源程序为一个模块 | MForcal | 是
ExeModule | 执行程序（模块） | MForcal | 是
DelModule | 删除模块 | MForcal | 是
SetResultBufMax | 设置自动保存运行结果的缓冲区的大小。 | GForcal | 是
DefExeModule | 按缺省方式执行模块，自动保存运行结果。 | GForcal | 是
GetResult | 获得运行结果。 | GForcal | 是
IsFcData | 判断是否是FcData数据 | FcData | 是
IntCal | 计算整数表达式的值 | Forcal | 是
RealCal | 计算实数表达式的值 | Forcal | 是
ComplexCal | 计算复数表达式的值 | Forcal | 是
SetFunction | 设置外部二级函数 | Forcal | 是
SetConst | 设置常量 | Forcal | 是
DeleteConstOrFunction | 删除常量或二级函数 | Forcal | 是
IsFor | 判断一个表达式是否有效 | Forcal | 是
GetFor | 获得表达式信息 | Forcal | 是
ParaModify | 判断表达式的自变量是否重新赋值 | Forcal | 是
GetForStr | 获得表达式中的字符串 | Forcal | 是
InsertKey | 插入一个键 | Forcal | 是
SearchKey | 查找一个键 | Forcal | 是
DeleteKey | 删除一个键 | Forcal | 是
DeletePrivateKey | 删除一个私有键 | Forcal | 是
EnumKeyTypeValue | 枚举指定键值类型所对应的所有字符串及键值 | Forcal | 是
LockKeyType | 锁定键的类型 | Forcal | 是
ExMsgWithForcal | 与Forcal交换信息 | Forcal | 是
SetStr | 向GForcal传送字符串。 | GForcal | 是
GetStr | 获得GForcal中的字符串。 | GForcal | 是
SetInts | 向GForcal传送整数数组。 | GForcal | 是
GetInts | 获得GForcal中的整数数组。 | GForcal | 是
SetReals | 向GForcal传送实数数组。 | GForcal | 是
GetReals | 获得GForcal中的实数数组。 | GForcal | 是

说明：

（1）许多函数需要互斥地使用Forcal资源，故这些函数在使用前，必须用函数UseForcal获得Forcal的使用权。

（2）来自Forcal32W.dll、MForcal32W.dll和FcData32W.dll中的函数，在GForcal中又加了一层包装，故速度稍慢。要获得更快的速度，可使用GetInstance和GetProcAddr函数直接获得相关函数的句柄。

[返回函数列表] InitGForcal：初始化GForcal

bool _stdcall InitGForcal(void);

说明：在使用GForcal之前必须用该函数初始化。初始化成功函数返回true。

[返回函数列表] FreeGForcal：释放GForcal

void _stdcall FreeGForcal(void);

说明：在使用完GForcal之后必须用该函数释放加载的资源。

[返回函数列表] GetInstance：得到Forcal32W.dll、MForcal32W.dll和FcData32W.dll的句柄

void _stdcall GetInstance(HINSTANCE &forcal,HINSTANCE &mforcal,HINSTANCE &fcdata);

说明：获得了这三个动态库的句柄后，可以用函数GetProcAddr获得相关动态库中的输出函数，这样可使用Forcal的全部功能，而且速度更快。

警告：不要从Forcal32W.dll中获得InitForcal和FreeForcal的函数句柄进行操作。

[返回函数列表] GetProcAddr：通过动态库句柄和函数名获得动态库的输出函数

说明：该函数与GetProcAddress的用法功能完全相同，提供该函数仅仅是为了方便使用。

[返回函数列表] LoadDll：加载Forcal扩展动态库

void _stdcall LoadDll(wchar_t *DllStr);

说明：

DllStr：含有Forcal扩展动态库名称的字符串。

允许加载多个Forcal扩展动态库。Forcal扩展动态库名字要放在双引号"..."之间。忽略在尖括号<"..." ...>内的Forcal扩展动态库。
例如："FcMath32W","d:\\forcal\\FcSystem32W.dll"

需要注意Forcal扩展动态库的加载顺序。

[返回函数列表] FreeDll：释放Forcal扩展动态库

void _stdcall FreeDll(void);

[返回函数列表] ReInitGFC：重新初始化GForcal

void _stdcall ReInitGFC(void);

说明：使GForcal恢复至InitGForcal时的状态。

[返回函数列表] SetResultBufMax：设置自动保存运行结果的缓冲区的大小

bool _stdcall SetResultBufMax(long k);

说明：在执行函数DefExeModule时，运行结果将保存到一个缓冲区中，该函数用于设置该缓冲区的大小。

[返回函数列表] DefExeModule：按缺省方式执行模块，自动保存运行结果

void _stdcall DefExeModule(void *hModule);

说明：hModule 为模块句柄。结果将保存在GForcal内置的缓冲区中。

[返回函数列表] GetResult：获得运行结果

void _stdcall GetResult(wchar_t *str, long strmax);

说明：strmax 为字符串 str 的大小。

[返回函数列表] SetStr：向GForcal传送字符串

bool _stdcall SetStr(wchar_t *str);

说明：

在GForcal中有一个缓冲区，主程序和缓冲区可以相互传送数据。在主程序中使用该函数可以将字符串传送到该缓冲区。

该函数总是从缓冲区的起始处存放数据，也就是说，每次调用该函数，以前存放的数据都会丢失。

[返回函数列表] GetStr：获得GForcal中的字符串

bool _stdcall GetStr(wchar_t *str, long strmax);

说明：

str：接收数据的缓冲区指针。
nstr：缓冲区 str 的大小。

在GForcal中有一个缓冲区，主程序和缓冲区可以相互传送数据。在主程序中使用该函数可以将缓冲区中的字符串传送到str中。若 strmax 太小，传送失败。

该函数总是从缓冲区的起始处获得数据。

[返回函数列表] SetInts：向GForcal传送整数数组

bool _stdcall SetInts(fcIFOR *xx,long xxmax);

说明：

xxmax 为整数数组 xx 的大小。

在GForcal中有一个缓冲区，主程序和缓冲区可以相互传送数据。在主程序中使用该函数可以将整数数组传送到该缓冲区。

该函数总是从缓冲区的起始处存放数据，也就是说，每次调用该函数，以前存放的数据都会丢失。

[返回函数列表] GetInts：获得GForcal中的整数数组

long _stdcall GetInts(fcIFOR *xx,long xxmax);

说明：

xx：接收数据的缓冲区指针。
xxmax：缓冲区xx的大小。

在GForcal中有一个缓冲区，主程序和缓冲区可以相互传送数据。在主程序中使用该函数可以将缓冲区中的整数数组传送到xx中。

该函数总是从缓冲区的起始处获得数据。该函数返回实际传送的数组元素个数。

若xx为NULL，或者 xxmax<=0，函数返回当前整数数组缓冲区的大小。

[返回函数列表] SetReals：向GForcal传送实数数组

bool _stdcall SetReals(double *xx,long xxmax);

说明：

xxmax 为实数数组 xx 的大小。

在GForcal中有一个缓冲区，主程序和缓冲区可以相互传送数据。在主程序中使用该函数可以将实数数组传送到该缓冲区。

该函数总是从缓冲区的起始处存放数据，也就是说，每次调用该函数，以前存放的数据都会丢失。

[返回函数列表] GetReals：获得GForcal中的实数数组

long _stdcall GetReals(double *xx,long xxmax);

说明：

xx：接收数据的缓冲区指针。
xxmax：缓冲区xx的大小。

在GForcal中有一个缓冲区，主程序和缓冲区可以相互传送数据。在主程序中使用该函数可以将缓冲区中的实数数组传送到xx中。

该函数总是从缓冲区的起始处获得数据。该函数返回实际传送的数组元素个数。

若xx为NULL，或者 xxmax<=0，函数返回当前实数数组缓冲区的大小。

2.2 Forcal脚本中可用的函数

2.2.1 向GForcal缓冲区传送数据[整数函数，实数函数]：FcSet(&i,x1,x2,... ...,xn)

在GForcal中有一个缓冲区，缓冲区和Forcal可以相互传送数据。缓冲区是一个一维数组，起始地址为0。在Forcal中使用 FcSet 函数可以将数据 x1,x2,... ...传送到该缓冲区自地址i开始的连续区域，函数返回下一个元素的地址（即元素xn后的地址，如果使用引用参数，i也指向该地址）。如果缓冲区没有足够的空间存放数据，该函数将自动扩充缓冲区的大小。

在整数表达式中，将把数据传送到整数缓冲区；在实数表达式中，将把数据传送到实数缓冲区。

该函数可能返回运行错误，错误代码1：非法的元素地址；2：无法分配内存。

FcSet 函数的特殊用法：

> FcSet(); //函数返回当前缓冲区大小
> FcSet(n); //创建至少能存放n个数据元素的缓冲区

一般，先用FcSet(n)创建能满足要求的缓冲区，然后存放数据，可提高运行效率。

2.2.2 从GForcal缓冲区获得数据[整数函数，实数函数]：FcGet(&i,&x1,&x2,... ...,&xn)

在GForcal中有一个缓冲区，缓冲区和Forcal可以相互传送数据。缓冲区是一个一维数组，起始地址为0。在Forcal中使用 FcGet 函数可以将缓冲区中从地址i开始的数据传送到 x1,x2,... ...,xn，必须使用引用参数，函数返回下一个元素的地址（即元素xn后的地址，如果使用引用参数，i也指向该地址）。

在整数表达式中，将获得整数缓冲区中的数据；在实数表达式中，将获得实数缓冲区中的数据。

该函数可能返回运行错误，错误代码1：非法的元素地址。

FcGet 函数的特殊用法：FcGet(); //函数返回当前缓冲区大小

2.2.3 向GForcal缓冲区传送UNICODE字符串[整数函数]：FcSetStr(Wstr)

在GForcal中有一个 UNICODE字符串缓冲区，该缓冲区可以和FcData一维wchar_s数组相互传送数据。在Forcal中使用 FcSetStr 函数可以将一维iwchar_s数组 Wstr 传送到该缓冲区，函数总是返回0。如果缓冲区没有足够的空间存放数据，该函数将自动扩充缓冲区的大小。该函数需要FcData32W.dll的支持。

在一维wchar_s数组中遇到0（UNICODE字符串结束标记）时将结束传送，如果没有0，将返回一个运行错误。

该函数可能返回运行错误，错误代码1：数组不存在；2：不是一维宽字符数组；3：内存错误；4：字符串没有结束标志0。

FcSetStr 函数的特殊用法：FcSetStr(0); //函数返回当前缓冲区大小

2.2.4 从GForcal缓冲区获得UNICODE字符串[整数函数]：FcGetStr(Wstr)

在GForcal中有一个 UNICODE字符串缓冲区，该缓冲区可以和FcData一维wchar_s数组相互传送数据。在Forcal中使用 FcGetStr 函数可以将缓冲区中的字符串传送到一维wchar_s数组 Wstr，函数总是返回0。该函数需要FcData32W.dll的支持。

该函数可能返回运行错误，错误代码1：数组不存在；2：不是一维宽字符数组；3：一维宽字符数组太小。

FcGetStr 函数的特殊用法：FcGetStr(0); //函数返回当前缓冲区大小

2.2.5 设置GForcal运行结果缓冲区大小[整数函数，实数函数]：SetResultBufMax(n)

该函数设置GForcal运行结果缓冲区的大小。函数总是返回实际的缓冲区大小。为了提高运行效率，一般在程序开头使用该函数。

3 例子 [返回页首]

这些例子体现了应用程序如何与Forcal系统进行交互，一般步骤是：

（1）使用函数InitGForcal进行初始化。

（2）使用函数LoadDll加载需要的Forcal扩展库。

（3）使用函数ComModule将字符串源代码编译为模块。

（4）使用函数DefExeModule或ExeModule执行模块，或者使用函数GetFor获取需要的表达式进行计算。

（5）使用函数ExMsgWithForcal获得数据类型标识，通过函数SearchKey或者IsFcData验证操作数据的类型，然后进行数据传送操作。或者使用函数SetStr、GetStr、SetInts、GetInts、SetReals、GetReals等传送数据。

（6）使用函数FreeDll卸载Forcal扩展库。

（7）使用函数FreeGForcal释放资源。

注意：许多函数需要用UseForcal获得Forcal的使用权后才能调用，用完后要及时归还Forcal使用权。

要演示这些例子，在编译时需要头文件forcal32w.h和gforcal32w.h，引入库GForcal32W.lib；在运行时需要GForcal32W.dll及支持库Forcal32W.dll、MForcal32W.dll和FcData32W.dll，以及相关Forcal扩展库的支持。

感谢刘圆圆先生（mgenx@live.com）为例子3.1～3.5编写了C#代码，下载：http://www.forcal.net/xiazai/forcal9/forcal9code.rar

3.1 使用缺省方式执行模块

本例子演示如何按缺省方式编译运行一段Forcal源代码，并获得运行结果。

C/C++源代码：

#include <windows.h>
#include <iostream>
#include <math.h>
#include "forcal32w.h"
#include "gforcal32w.h"
#pragma comment( lib, "GForcal32W.lib" )
using namespace std;
void main(void)
{
wchar_t str1[]=L"f(x,y)=x+y; 3+f(1,2); c: 2-sin[3i];"; //存放Forcal表达式
const int StrMax=100;
wchar_t str2[StrMax];
fcVOID nModule;
void *hModule;
fcINT err1,err2;
int n;
wcout.imbue(locale("chs")); //设置输出的locale为中文
wcin.imbue(locale("chs")); //设置输入的locale为中文
InitGForcal(); //初始化GForcal
if(!UseForcal(2)) //申请使用Forcal
{
nModule=0; //由MForcal自动指定模块号
n=ComModule(str1,nModule,hModule,err1,err2); //将字符串源代码编译为模块
if(n==0)
{
SetResultBufMax(StrMax); //设置存放运行结果的缓冲区
DefExeModule(hModule); //按缺省方式执行模块
GetResult(str2, StrMax); //得到运行结果
wcout<<str2; //输出运行结果
}
UseForcal(0); //归还Forcal的使用权
}
wcin.get();
FreeGForcal(); //释放GForcal
}

运行结果：

6.
c: 2.-10.0178749274099i

3.2 使用自定义方式执行模块

本例子演示如何按自定义方式编译运行一段Forcal源代码，并输出运行结果。

C/C++源代码：

#include <windows.h>
#include <iostream>
#include <math.h>
#include "forcal32w.h"
#include "gforcal32w.h"
#pragma comment( lib, "GForcal32W.lib" )
using namespace std;
void _stdcall myFcMessage(wchar_t *str) //输出一个字符串
{
wcout<<str;
}
void _stdcall outi(fcIFOR ll) //输出一个整数
{
wchar_t wchNum[32];
myFcMessage(L"\r\ni: ");
_i64tow_s(ll,wchNum,32,10);
myFcMessage(wchNum);
}
void _stdcall outd(double dd) //输出一个实数
{
char chNum[32];
wchar_t wchNum[32];
int i;
myFcMessage(L"\r\n");
_gcvt_s(chNum,32,dd,16);
for(i=0;chNum[i];i++) {wchNum[i]=chNum[i];}
wchNum[i]='\0';
myFcMessage(wchNum);
}
void _stdcall outc(_complex cc) //输出一个复数
{
char chNum[32];
wchar_t wchNum[32];
int i;
myFcMessage(L"\r\nc: ");
_gcvt_s(chNum,32,cc.x,16);
for(i=0;chNum[i];i++) {wchNum[i]=chNum[i];}
wchNum[i]='\0';
myFcMessage(wchNum);
if(cc.y!=0.0)
{
if(cc.y>0.0) myFcMessage(L"+");
_gcvt_s(chNum,32,cc.y,16);
for(i=0;chNum[i];i++) {wchNum[i]=chNum[i];}
wchNum[i]='\0';
myFcMessage(wchNum);
myFcMessage(L"i");
}
}
void main(void)
{
wchar_t str1[]=L"f(x,y)=x+y; 3+f(1,2); c: 2-sin[3i];"; //存放Forcal表达式
fcVOID nModule;
void *hModule;
fcINT err1,err2;
int n;
void *vv;
wcout.imbue(locale("chs")); //设置输出的locale为中文
wcin.imbue(locale("chs")); //设置输入的locale为中文
InitGForcal(); //初始化GForcal
if(!UseForcal(2)) //申请使用Forcal
{
nModule=0; //由MForcal自动指定模块号
n=ComModule(str1,nModule,hModule,err1,err2); //将字符串源代码编译为模块
if(n==0)
{
vv=myFcMessage;
InsertKey("FcMessage",9,FC_Key_User,myFcMessage,NULL,vv); //将函数myFcMessage注册到Forcal
ExeModule(hModule,outi,outd,outc); //执行模块
}
UseForcal(0); //归还Forcal的使用权
}
wcin.get();
FreeGForcal(); //释放GForcal
}

运行结果：

6.
c: 2.-10.0178749274099i

3.3 使用Forcal脚本中的全局函数

本例子演示了如何使用Forcal系统中定义的全局函数，但私有函数是无法获得的。通过全局函数，可以方便地与Forcal系统中的静态变量、模块变量以及全局变量进行交互，这些变量可以是任意的对象。

C/C++源代码：

#include <windows.h>
#include <iostream>
#include <math.h>
#include "forcal32w.h"
#include "gforcal32w.h"
#pragma comment( lib, "GForcal32W.lib" )
using namespace std;
void main(void)
{
wchar_t str1[]=L"f(x,y)=x+y; ~g(x,y)=3+f(x,y); ~h(x,y)=x-f(3,y);"; //存放Forcal表达式
fcVOID nModule;
void *hModule,*myFor,*Para;
fcINT err1,err2,PareNum;
double xx[2]={1,2}; //作为自变量参数
wcout.imbue(locale("chs")); //设置输出的locale为中文
wcin.imbue(locale("chs")); //设置输入的locale为中文
InitGForcal(); //初始化GForcal
if(!UseForcal(2)) //申请使用Forcal
{
nModule=0; //由MForcal自动指定模块号
ComModule(str1,nModule,hModule,err1,err2); //将字符串源代码编译为模块
if(GetFor(L"g",2,NULL,nModule,myFor,Para,PareNum)) //查找全局函数g
{
if(PareNum==1) //函数有2个自变量
{
wcout<<RealCal(myFor,xx)<<L"\r\n"; //计算并输出结果
}
}
if(GetFor(L"h",2,NULL,nModule,myFor,Para,PareNum)) //查找全局函数h
{
if(PareNum==1) //函数有2个自变量
{
wcout<<RealCal(myFor,xx); //计算并输出结果
}
}
UseForcal(0); //归还Forcal的使用权
}
wcin.get();
FreeGForcal(); //释放GForcal
}

运行结果：

6
-4

3.4 操作Forcal系统中的数组对象

本例子演示了如何操作Forcal系统中的数组对象，同时也演示了如何加载使用Forcal扩展库。演示要点如下：

（1）加载Forcal扩展库 FcMath32W.dll。

（2）获取并运行了Forcal脚本中的全局函数a，该函数返回一个FcData数组对象。

（3）验证该数组对象，并赋初值。

（4）获取并运行了Forcal脚本中的全局函数b，该函数对传入的数组的每一个元素加1。

（5）验证该数组对象仍然有效，并输出最终结果。

（6）卸载Forcal扩展库。

C/C++源代码：

#include <windows.h>
#include <iostream>
#include <math.h>
#include "forcal32w.h"
#include "gforcal32w.h"
#pragma comment( lib, "GForcal32W.lib" )
using namespace std;
void main(void)
{
wchar_t str1[]=L"~a(:static,aa)= if[!aa,aa=math::array(3).free()], aa; ~b(x:i,k)= k=FCDLen(x), i=0,(i<k).while{x[i]=x[i]+1, i++};"; //存放Forcal表达式
fcVOID nModule,i;
void *hModule,*aFor,*bFor,*Para;
fcINT err1,err2,PareNum;
fcdTYPE real_s,BasicType;
FCDArrayS *pFCDArrayS;
double xx[1],x,*px;
wcout.imbue(locale("chs")); //设置输出的locale为中文
wcin.imbue(locale("chs")); //设置输入的locale为中文
InitGForcal(); //初始化GForcal
LoadDll(L"\"FcDll\\FcMath32W.dll\""); //加载Forcal扩展库
if(!UseForcal(2)) //申请使用Forcal
{
//查找注册到Forcal中的FcData实数数组类型标识
real_s=(fcdTYPE)*(fcIFOR *)ExMsgWithForcal(Key_IntConst,L"real_s",Para,Para);
nModule=0; //由MForcal自动指定模块号
ComModule(str1,nModule,hModule,err1,err2); //将字符串源代码编译为模块
if(GetFor(L"a",2,NULL,nModule,aFor,Para,PareNum)) //查找全局函数a
{
if(PareNum==-1) //函数有0个自变量
{
x=RealCal(aFor,xx); //计算结果为一个实数数组
}
}
IsFcData(*(fcIFOR *)&x,BasicType); //判断x是否是FcData数据
if(BasicType==real_s) //实数数组
{
pFCDArrayS=(FCDArrayS *)*(fcVOID *)&x;
px=(double *)pFCDArrayS->ArrayS;
for(i=0;i<pFCDArrayS->Dimension[1];i++)
{
px[i]=i; //数组元素赋值为连续整数
}
}
if(GetFor(L"b",2,NULL,nModule,bFor,Para,PareNum)) //查找全局函数b
{
if(PareNum==0) //函数有1个自变量
{
xx[0]=x; //执行脚本函数b(x)
RealCal(bFor,xx);
}
}
IsFcData(*(fcIFOR *)&x,BasicType); //判断x是否仍然是FcData数据
if(BasicType==real_s) //实数数组
{
pFCDArrayS=(FCDArrayS *)*(fcVOID *)&x;
px=(double *)pFCDArrayS->ArrayS;
for(i=0;i<pFCDArrayS->Dimension[1];i++)
{
wcout<<px[i]<<L" ";
}
}
UseForcal(0); //归还Forcal的使用权
}
wcin.get();
FreeDll(); //卸载Forcal扩展库
FreeGForcal(); //释放GForcal
}

运行结果：

1 2 3

3.5 通过GForcal的输出函数交互数据

本例子演示了如何通过GForcal的输出函数与Forcal系统交互数据。演示要点如下：

（1）通过函数 SetReals 向GForcal缓冲区传送数据，是一个实数数组。

（2）获取并运行了Forcal脚本中的全局函数a，该函数对传入的每一个数据元素加1。

（3）通过函数 GetReals 获得GForcal缓冲区中的实数数组数据。

C/C++源代码：

#include <windows.h>
#include <iostream>
#include <math.h>
#include "forcal32w.h"
#include "gforcal32w.h"
#pragma comment( lib, "GForcal32W.lib" )
using namespace std;
void main(void)
{
wchar_t str1[]=L"~a(:i,k,x)= k=FcGet(), i=0,(i<k).while{FcGet(i,&x), FcSet(i,x+1), i++};"; //存放Forcal表达式
fcVOID nModule;
void *hModule,*myFor,*Para;
fcINT err1,err2,PareNum;
double xx[3]={0,1,2};
wcout.imbue(locale("chs")); //设置输出的locale为中文
wcin.imbue(locale("chs")); //设置输入的locale为中文
InitGForcal(); //初始化GForcal
if(!UseForcal(2)) //申请使用Forcal
{
nModule=0; //由MForcal自动指定模块号
ComModule(str1,nModule,hModule,err1,err2); //将字符串源代码编译为模块
SetReals(xx,3); //向GForcal缓冲区传送数据
if(GetFor(L"a",2,NULL,nModule,myFor,Para,PareNum)) //查找全局函数a
{
if(PareNum==-1) //函数有0个自变量
{
RealCal(myFor,xx);
}
}
GetReals(xx,3); //从GForcal缓冲区获得数据
wcout<<xx[0]<<L" "<<xx[1]<<L" "<<xx[2];
UseForcal(0); //归还Forcal的使用权
}
wcin.get();
FreeGForcal(); //释放GForcal
}

运行结果：

1 2 3

3.6 操作来自Forcal扩展库中的 任意对象

任意对象都可以注册到Forcal中，参考：如何在FORCAL中添加对象、如何在FORCAL扩展库中添加对象。一般，对象有2种：

（1）用函数 InsertKey 注册的对象。这类对象可通过函数 SearchKey 获取和验证。对象标识是一个 fcKEY 整数，要将该标识注册为Forcal常量。

（2）通过FcData注册的对象。这类对象可参考3.4中的操作。对象标识是一个 fcdTYPE 整数，要将该标识注册为Forcal常量。

无论哪种对象，必须知道该对象的标识和对象的定义。对象标识应已经注册为Forcal常量，故可用函数 ExMsgWithForcal 获取；对象的定义由对象的设计者提供。

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