欢迎访问 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
最近更新: 2010年08月22日