在程序中加载使用OpenForcal.dll

目  录

1、OpenForcal的输出函数
2、如何加载使用
OpenForcal
3、最简单的例子
4、简单的例子
5、使用更多功能的例子


1、OpenForcal的输出函数  [目录]

1.1 初始化动态库:bool InitDll(char *pIni,char *pHlp);

    pIni为初始化文件名(含文件路径),如果设为NULL,OpenForcal将自动在当前目录中搜索OpenFC.ini进行加载;任何情况下,若加载不成功,OpenForcal将按缺省值进行初始化。
    pHlp为动态库说明文件名(含文件路径),如果设为NULL,OpenForcal将自动在当前目录中搜索OpenFChlp.ini进行加载。动态库说明文件的格式请参考“如何对OpenForcal进行功能扩展->3 如何编写动态库函数说明文件”。
    初始化成功时返回true。

1.2 编译源程序:int ComFor(char *FcStr,char *&ErrStr,void (*outl)(long ),void (*outd)(double ),void (*outc)(_complex ),void (*myMessage)(char *));

    FcStr为指向源程序字符串的指针;ErrStr返回编译信息;outl(输出整数表达式的值)、outd(输出实数表达式的值)、outc(输出复数表达式的值)、myMessage(输出字符串信息)四个函数在执行表达式时被调用,输出信息,这四个参数也可设为NULL。该函数返回值的意义如下:
    ComFor=0,编译成功。
    ComFor=-1,禁止编译执行表达式,表示OpenForcal要释放动态库,因此要做好退出前的清理工作。
    ComFor=-2,表示资源被占用,无法对源程序进行编译,可稍后重新进行编译;
    ComFor=-3,没有表达式;
    ComFor=-4,内存错误;
    ComFor=-5,预编译错误;
    ComFor=-6,注释符号/* ... */不成对;
    ComFor=-7,文件太长,需重新设置文件最大长度;
    ComFor=-8,不能使用FORCAL;
    ComFor=-9,表达式太长;
    ComFor=-10,整数表达式不够用,需重新设置;
    ComFor=-11,复数表达式不够用,需重新设置;
    ComFor=-12,实数表达式不够用,需重新设置;
    ComFor=-13,不能正常设置一个常量;
    ComFor=-14,常量定义错误,常量名由ErrStr返回;
    ComFor=-15,不能正常设置一个自动常量;
    ComFor=-16,自动常量定义错误,自动常量名由ErrStr返回;
    ComFor=1,不正确的运算方式;
    ComFor=2,无表达式;
    ComFor=3,变量说明错,等号前有非法字符;
    ComFor=4,变量应放在 ( ) 内;
    ComFor=5,非法变量字符(以英文字母开头的英文字母与数字的组合);
    ComFor=6,变量名以英文字母开头;
    ComFor=7,变量重复说明;
    ComFor=8,括号不成对;
    ComFor=9,在复数计算时,不能用 i 作为变量(该返回值在编译复数表达式时使用);
    ComFor=10,不可识别函数名;
    ComFor=11,数学表达式太长,接近32766个字符;
    ComFor=12,不可识别变量;
    ComFor=13,数字错误;
    ComFor=14,不可识别字符、函数名、变量名或者一级函数有多个自变量;
    ComFor=15,内存分配失败;
    ComFor=16,二级函数错误;
    ComFor=17,符号定义错误或无表达式或括号不成对;
    ComFor=18,表达式中的字符串无效,即"..."不匹配;
    ComFor=19,没有启用forcal的字符串处理功能;
    ComFor=20,表达式中的字符串太多或表达式太长;
    ComFor=21,内存分配失败;
    ComFor=22,找不到字符串$"..."所表示的表达式的类型;
    ComFor=23,找不到字符串#"..."所表示的表达式的序号;
    ComFor=24,找不到字符串&"..."或@"..."的地址;
    ComFor=25,字符串数组不够用,需重新设置;
    ComFor=26,超出共享版允许的字符限制,请注册使用正式版[在正式版中无此返回值];

1.3 执行程序 int ExeFor(long Begin,long end,int mode);

    Begin为开始执行的起始地址,End为结束地址,这两个地址可在OpenForcal主程序中由GetAddress[]函数获得。mode用于设置运行模式。
    mode=1:执行编译表达式时设定的输出函数,且遇到另一个程序正在运行时返回代码2;
    mode=2:执行编译表达式时设定的输出函数,且遇到另一个程序正在运行时不返回代码2,等待运行;
    mode=3:不执行编译表达式时设定的输出函数,且遇到另一个程序正在运行时返回代码2;
    mode=4:不执行编译表达式时设定的输出函数,且遇到另一个程序正在运行时不返回代码2,等待运行;
    该函数返回值意义如下:
    ExeFor=0,正常执行程序;
    ExeFor=-1,禁止编译执行表达式,表示OpenForcal要释放动态库,因此要做好退出前的清理工作;
    ExeFor=1,程序没有编译,不能运行;
    ExeFor=2,另一个程序正在运行,不能同时执行,当mode=1或mode=3时返回该参数;
    ExeFor=3,运行地址错误,表示Begin或End非法;

    如果ExeFor以mode=3或mode=4方式运行,只能禁止编译表达式时设定的输出函数的输出,并不能禁止其他动态库中任何形式的输出,在OpenForcal的源程序中需要特别注意这一点。
   

1.4 释放动态库:void FreeDll(void);

1.5 自定义预编译处理程序:void PreCom(bool (*pPreCom)(char *&str));

    PreCom可以将主调程序中预编译处理函数pPreCom(在主调程序中定义)的地址传送给OpenForcal,在每一次编译源程序之前,OpenForcal都将调用主调程序的预编译处理函数pPreCom对源程序进行预处理。
    其中字符串指针str指向存放源程序的地址,除了不能用该指针释放该地址空间之外,可以进行其他任意的操作,包括将该指针指向另一个地址空间。
    预编译没有错误时返回true。

1.6 向OpenForcal发送信息:void DllMessage(pSetMyMessage );

   调用 DllMessage可以获得OpenForcal传送过来的用于向OpenForcal发送信息的函数的地址,其中pSetMyMessage的类型定义如下:
    typedef void (* pMyMessage) (char *);
    typedef void (* pSetMyMessage) (pMyMessage);
    在主调程序中定义一个pSetMyMessage类型的函数,函数说明如下:
    void GetDllMessage(pMyMessage );
    pMyMessage pMyMessagep=NULL;//接受信息函数的地址;
    函数定义:
   void GetDllMessage(pMyMessage p) {pMyMessagep=p;} 
   在主调程序中可以调用DllMessage(GetDllMessage)函数将GetDllMessage的地址传送给OpenForcal。这样,在每次编译源程序之前,OpenForcal都会调用GetDllMessage()函数,将信息函数的地址(即ComFor(...)函数中的myMessage参数)传送给主调程序。因此,在主调程序中使用pMyMessagep()函数向OpenForcal发送信息,就是调用myMessage()函数发送信息。例如:
    pMyMessagep("\r\n这里是预处理程序!\r\n");

1.7 定义可由OpenForcal调用的实数函数:void RegRealFun(char **ppchRealNameDll,int *piRealParaDll,double (**ppRealFunDll)(int ,double *));

    RegRealFun用于向OpenForcal注册实数函数。字符串数组ppchRealNameDll存放函数名,整数数组piRealParaDll存放自变量个数,函数指针数组ppRealFunDll存放函数地址。
    实数函数均具有以下形式;
    double rfc_add(int ,double *);
    double rfc_sub(int ,double *);
    double rfc_nstr(int ,double *);
    以下定义中ppchRealNameDll、piRealParaDll、ppRealFunDll的参数要对应。
    char *ppchRealNameDll[]={"add","sub","nstr",""}; //定义在OpenForcal源程序中使用的函数名;
    int piRealParaDll[]={1,1,1}; //-2表示有不确定的多个自变量,-1表示有0个自变量,0表示有1个自变量,1表示有2个自变量;
    double (*ppRealFunDll[])(int ,double *)={rfc_add,rfc_sub,rfc_nstr}; //函数指针数组;
    请参考FORCAL使用说明1.6中的11、“设置可由FORCAL调用的外部函数”。

1.8 定义可由OpenForcal调用的整数函数:void RegIntFun(char **,int *,long (**)(int ,long *));

    RegIntFun用于向OpenForcal注册整数函数。该部分的说明与“可由OpenForcal调用的实数函数”类似,请参考1.7中的说明。

1.9 定义可由OpenForcal调用的复数函数:void RegComplexFun(char **,int *,_complex (**)(int ,_complex *));

    RegComplexFun用于向OpenForcal注册复数函数。该部分的说明与“可由OpenForcal调用的实数函数”类似,请参考1.7中的说明。

1.10 使用字符串:void GetFcStr(char **&ppchFcStr,long *&plFcStrMax,long &StrsMax);

    ppchFcStr为字符串数组指针;plFcStrMax指向一个存放字符串大小的长整形数组,该数组与ppchFcStr相对应,指出了ppchFcStr中各个字符串的大小;StrsMax为字符串数组ppchFcStr的大小。
    请参考FORCAL使用说明中的字符数据处理。
    使用FORCAL字符串需要注意以下问题:
    (1)、使用字符串之前先检查地址是否有效,字符串地址用一个整数表示,0<=地址<StrsMax;
    (2)、如果释放了一个字符串,把该指针置为NULL,同时将串的大小置为0。

1.11 使用Forcal实数表达式:void GetRealFor(double (*&pRCALS)(int ),int (*&pFCERRNUM)(void),void (*&pSETFCERR)(int ,char *),bool *&fortrue,double **&allin,int *&forpara,int &rfor_max);

    pRCALS:计算实数表达式的值;
    pFCERRNUM:获得Forcal中实数表达式运行错误代码,0表示没有错误;
    pSETFCERR:设置外部函数运行错误,字符串指针指出出错函数名;
    fortrue:存放各个实数表达式的编译状态,表达式编译通过时设为true;
    allin:allin指向存放各实数表达式自变量的指针数组;
    forpara:存放各个实数表达式的自变量个数;
    rfor_max:最多可用的实数表达式数目。
    请参考FORCAL使用说明1.6中相关函数的说明。
    使用FORCAL表达式进行计算需要注意以下问题:
    (1)、检查rfor_max是否大于0,rfor_max>0时可以使用表达式,在OpenForcal中,rfor_max总是大于0,因此也可以不检查此项;
    (2)、检查表达式是否存在,0<=表达式序号<rfor_max;
    (3)、检查表达式编译是否通过,fortrue[表达式序号]=true时可以使用;
    (4)、检查表达式参数个数是否匹配;
    (5)、用pfcerrnum()函数可以获得FORCAL运行错误,出现错误时不再进行计算;
    (6)、如果pfcerrnum()==0,可以用psetfcerr()函数向FORCAL报告错误;
    (7)、一般情况下,FORCAL函数不允许递归。终止递归的方法是设置一个静态变量,用以记录该函数被调用的次数,当被调用的次数大于setstackmax(n)函数的设定值时,即认为出现了递归。当然,这种检测递归的方法同时也限制了该函数被嵌套调用的次数。

1.12 使用Forcal整数表达式:void GetIntFor(pICALS &,pIFCERRNUM &,pISETFCERR &,bool *&,long **&,int *&,int &);

    该部分的说明与“使用Forcal实数表达式”类似,请参考1.11中的说明。

1.13 使用Forcal复数表达式:void GetComplexFor(pCCALS &,pCFCERRNUM &,pCSETFCERR &,bool *&,_complex **&,int *&,int &);

    该部分的说明与“使用Forcal实数表达式”类似,请参考1.11中的说明。

1.14 使用FORCAL实数数组:void GetFcDoubleArray(pGETFCDOUBLEARRAYS &pGETFCDOUBLEARRAYSp);

    由GetFcDoubleArray可以获得一个函数的地址pGETFCDOUBLEARRAYSp,由该函数可以获得FORCAL实数数组的地址信息。该函数的类型定义如下:
    typedef double **(* pGETFCDOUBLEARRAYS) (long &,long *&);
    pGETFCDOUBLEARRAYS pGETFCDOUBLEARRAYSp;
    若定义:
    double **ppfcdoublearray; //多维存储数组doublearray的指针;
    long fcdoublearrayMax; //多维存储数组doublearray的大小;
    long *pfcdoublearrayMax; //多维存储数组doublearray中各维数组长度的整数组的指针;
    则由ppfcdoublearray=pGETFCDOUBLEARRAYSp(fcdoublearrayMax,pfcdoublearrayMax);获得FORCAL实数数组的地址信息。

    请参考FORCAL使用说明1.6中相关函数的说明。
    使用FORCAL数组需要注意以下问题:
    (1)、检查ppfcdoublearray是否为真,ppfcdoublearray为真时可以使用数组;
    (2)、检查数组是否存在,0<=数组序号fcdoublearrayMax<rfor_max;
    (3)、使用数组不要越界。

1.15 使用FORCAL复数数组:void GetFcComplexArray(pCGETFCCOMPLEXARRAYS &);

    该部分的说明与“使用FORCAL实数数组”类似,请参考1.14中的说明。

1.16 使用FORCAL整数数组:void GetFcLongArray(pIGETFCLONGARRAYS &);

    该部分的说明与“使用FORCAL实数数组”类似,请参考1.14中的说明。

1.17 获得OpenForcal的设置:void GetOpenFcSet(long &textmax,int &intmax,int &realmax,int &complexmax,long &strmax,char *&pch,char *&pdllfile);

    textmax:源程序最大长度;
    intmax:整数表达式最多个数;
    realmax:实数表达式最多个数;
    complexmax:复数表达式最多个数;
    strmax:最多可用的字符串个数;
    pch:扩展动态库文件,多个文件之间用空格、Tab键或者换行符分隔,注意以字符*开头的文件被忽略,在<...>中的文件被忽略(字符“<”应在某个文件名的开头);
    pdllfile :扩展动态库说明文件,多个文件之间用空格、Tab键或者换行符分隔,注意以字符*开头的文件被忽略,在<...>中的文件被忽略(字符“<”应在某个文件名的开头)。

1.18 设置OpenForcal:int SetOpenFcSet(long textmax,int intmax,int realmax,int complexmax,long strmax,char *pch);

    textmax:源程序最大长度;
    intmax:整数表达式最多个数;
    realmax:实数表达式最多个数;
    complexmax:复数表达式最多个数;
    strmax:最多可用的字符串个数;
    pch:扩展动态库文件,多个文件之间用空格、Tab键或者换行符分隔,注意以字符*开头的文件被忽略,在<...>中的文件被忽略(字符“<”应在某个文件名的开头)。
    函数返回值的意义如下:
    0、设置成功;
    1、未注册用户,没有设置文件最大长度,其他项设置成功。
    2、内存分配错误。
    3、FORCAL设置错误;
    4、加载扩展动态库时出现致命错误。

1.19 加载动态库说明文件:bool LoadDllFunFile(char *pch);

    若加载成功返回true,否则返回false。
    pch:扩展动态库说明文件,多个文件之间用空格、Tab键或者换行符分隔,注意以字符*开头的文件被忽略,在<...>中的文件被忽略(字符“<”应在某个文件名的开头)。
    在该函数执行结束之前,应禁止通过pDllFunFile进行任何操作(无论是在主调程序还是在OpenForcal的扩展动态库中),pDllFunFile是通过pDllFunFile=GetDllFunFile()获得的指向动态库说明文件地址的指针。

1.20 使用Openforcal的临界区:void OfcCriticalSection(int inout);

    inout=1,进入临界区,但并不禁止源代码的编译和执行,动态库的说明信息,只许读,不许写;
    inout=1,进入临界区,同时禁止源代码的编译和执行,允许读写动态库说明信息;
    inout=0,离开临界区。
    注意:不要在临界区中使用OpenForcal扩展动态库的任何一个输出函数。
    通常,使用动态库的说明信息时需要在临界区中进行。例如:
    OfcCriticalSection(1);//进入临界区;
    //...访问动态库的说明信息...

    OfcCriticalSection(0);
//离开临界区;

1.21 得到动态库的说明信息:DllFunFile *GetDllFunFile();

    类DllFunFile的类型定义如下:
    class DllFunChar
    {public:
     char *pstrname,*pstr;
    
DllFunChar *headDllFunChar,*endDllFunChar;
    
DllFunChar();
    
DllFunChar(DllFunChar *);
    
~DllFunChar();
    
bool setDllFunCharName(char *);
    
bool setDllFunChar(char *);
    };
    class DllFunFile
    {public:
    
char *DllFunFilename;
    
DllFunChar *pDllFunChar,head_DllFunChar;
    
DllFunFile *headDllFunFile,*endDllFunFile;
    
DllFunFile();
    
DllFunFile(DllFunFile *);
    
~DllFunFile();
    
bool setDllFunFilename(char *);
    };
    该类中数据成员的说明请参考“如何对OpenForcal进行功能扩展”中“3 如何编写动态库函数说明文件 ”。

1.22 获得或设置主程序初始化信息:char *ExternIniText(char *pch);

    OpenForcal可以为主程序保存初始化信息。使用方法如下:
   
ExternIniText(NULL):获得初始化信息,该函数通常在程序开始时调用。
   
ExternIniText(pch):保存初始化信息,pch为信息字符串,该函数通常在程序结束前调用。
    该函数返回当前初始化信息字符串;若该函数返回NULL,则发生内存错误。


2 如何加载使用OpenForcal  [目录]

2.1 OpenForcal的初始化及加载

    首先,必须有forcal.dll的支持,OpenForcal才能进行工作,以后我们总是假定能正常的加载使用forcal.dll,把forcal.dll放到windows的搜索路径内或者把forcal.dll和OpenForcal放在一起即可做到这一点。
    OpenForcal提供了带参数的的初始化函数bool InitDll(char *pIni,char *pHlp),因此,我们可以将加载OpenForcal的程序和OpenForcal.dll分别存放在硬盘的不同位置,这不但不会影响程序的性能,而且效率更高。无论使用OpenForcal的程序有多少,硬盘上可以只保留一个OpenForcal.dll文件,节省了磁盘空间;同时,不同的程序使用保存在不同位置的初始化文件对OpenForcal进行初始化,相互之间没有任何影响。
    一般要将OpenForcal.dll放到windows的搜索路径内。
    要使用显式方式链接动态库OpenForcal.dll。

2.2 函数的使用次序

    (1)如果要向OpenForcal注册可由Forcal调用的外部函数,必须在初始化之前进行,即RegRealFun()、RegIntFun()、RegComplexFun()三个函数要在InitDll()之前使用。
    (2)用InitDll()函数初始化OpenForcal。通常,在调用InitDll()函数之前,不要调用下面除FreeDll()之外的任何函数。
    (3)可以调用GetRealFor()、GetIntFor()、GetComplexFor()三个函数以便使用Forcal的实数、整数和复数表达式;可以调用GetFcStr()以便使用Forcal字符串。
    (4)可以调用GetFcDoubleArray()、GetFcComplexArray()、GetFcLongArray()以便使用Forcal的实数、复数和整数数组;可以调用PreCom()设置主调程序的预处理函数;可以调用DllMessage()函数以便向OpenForcal发送信息。
    (5)用ComFor()编译源程序之后,可以多次调用ExeFor()进行计算。(1~4)中的函数只能在使用ComFor()和ExeFor()之前调用。
    (6)可以调用GetOpenFcSet()获得OpenForcal的当前设置。
    (7)可以调用GetDllFunFile()获取动态库的说明信息。
    (8)可以调用SetOpenFcSet()函数对OpenForcal重新进行设置,重新设置后,必须重新调用(3)中的函数(如果这些函数在以前使用过)。重新设置后,将丢失以前的编译结果。
    (9)可以调用LoadDllFunFile()函数重新加载动态库说明文件。
    (10)可以调用
ExternIniText()函数获得或设置主程序初始化信息
    (11)只要使用了前面的任何一个函数,程序退出时,都要用FreeDll()释放OpenForcal。

2.3 最简单的使用方式

    (1)用InitDll函数初始化动态库;
    (2)用ComFor函数编译源程序;
    (3)用ExeFor函数执行程序;
    (4)用FreeDll函数释放动态库。

2.4 使用OpenForcal.dll的其他功能

    请参考“1、OpenForcal的输出函数”中其他函数的说明。


3 最简单的例子  [目录]

#include <windows.h>
#include <iostream.h>

HINSTANCE OpenForcalDll;//存放动态库的地址;
//得到初始化动态库函数的地址;
typedef bool (* pInitDll)(char *,char *);
pInitDll pInitDllp;
//得到释放动态库函数的地址;
typedef void (* pFreeDll)(void);
pFreeDll pFreeDllp;

void main()
{OpenForcalDll=LoadLibrary("OpenForcal.dll");
 if(OpenForcalDll)
 {pInitDllp=(pInitDll) GetProcAddress(OpenForcalDll,"InitDll");
  pInitDllp(NULL,NULL); //初始化动态库;
  pFreeDllp=(pFreeDll) GetProcAddress(OpenForcalDll,"FreeDll");
 }
 else
 {MessageBox(NULL,"找不到动态库OpenForcal.dll,请将OpenForcal.dll放到Windows的搜索路径内!","SimpleOpenFC",MB_OK);}

 cout<<"最简单的使用OpenForcal的例子。\r\n需要扩展动态库FcWin.dll的支持,在FcWin窗口进行操作。\r\n按回车键Enter结束程序 !";
 cin.get();

 if(OpenForcalDll) {pFreeDllp(); FreeLibrary(OpenForcalDll);} //释放动态库;
}


4 简单的例子  [目录]

    用Visual C++6.0向导建立一个MFC AppWizard(exe)工程,工程名为SimpleOpenFC,除应用程序类型选择Dialog based外,其余使用默认选项。工程建好后,选择菜单Build->Set Active Configuration中Wiin32 Release选项进行编译。
    我们在对话框窗口上放置两个文本编辑框和一个“计算”按钮。两个文本编辑框中其中一个编辑框的ID改为IDC_text,添加一个CEdit控件m_text,用于接收源程序文件;另一个编辑框的ID改为IDC_out,添加一个CEdit控件m_out,用于输出计算结果。“计算”按钮的ID改为IDC_cal,为单击该按钮添加一个函数。添加一个程序退出时被自动执行的函数DestroyWindow()。
    进行完以上工作,打开文件SimpleOpenFCDlg.cpp,我们将在该文件中添加有关内容。
    首先在文件开头添加下面一行 ,以便使我们能够使用数学函数:

    #include "math.h" //使用数学函数;

    接下来在文件说明部分添加如下全局常量定义和函数说明: 

    HINSTANCE OpenForcalDll;//存放动态库的地址;

    //得到初始化动态库函数的地址;
    typedef bool (* pInitDll)(char *,char *);
    pInitDll pInitDllp;
    //得到释放动态库函数的地址;
    typedef void (* pFreeDll)(void);
    pFreeDll pFreeDllp;
    //得到编译函数的地址;
    typedef void (* pCOMPLEXfun) (_complex );
    typedef void (* pDOUBLEfun) (double );
    typedef void (* pLONGfun) (long );
    typedef void (* pDllMessage) (char *);
    void outl(long);
    void outd(double);
    void outc(_complex);
    void DllMessage(char *);

    typedef int (* pComFor) (char *,char *&,pLONGfun ,pDOUBLEfun ,pCOMPLEXfun ,pDllMessage);
    pComFor pComForp;
    //得到计算函数的地址;
    typedef int (* pExeFor) (long ,long ,int);
    pExeFor pExeForp;

    //保存输出窗口的地址;
    CEdit *pout;

    下面添加函数实现。
    找到CSimpleOpenFCDlg::OnInitDialog()函数,添加如下初始化内容:

    // TODO: Add extra initialization here

    OpenForcalDll=NULL;
    OpenForcalDll=LoadLibrary("OpenForcal.dll");
    if(OpenForcalDll)
    {pComForp=(pComFor) GetProcAddress(OpenForcalDll,"ComFor");
     pExeForp=(pExeFor) GetProcAddress(OpenForcalDll,"ExeFor");
     pInitDllp=(pInitDll) GetProcAddress(OpenForcalDll,"InitDll");
     pInitDllp(NULL,NULL); //初始化动态库;
     pFreeDllp=(pFreeDll) GetProcAddress(OpenForcalDll,"FreeDll");
    }
    else
    {AfxMessageBox("找不到动态库OpenForcal.dll,请将OpenForcal.dll放到Windows的搜索路径内!",MB_OK,0);}

    pout=&m_out;//保存输出窗口的地址;

    找到CSimpleOpenFCDlg::Oncal()函数,修改该函数的内容如下,当单击“计算”按钮时,将执行该函数:

    void CSimpleOpenFCDlg::Oncal() 
    {
     // TODO: Add your control notification handler code here
     CString textstr;
     int n;
     char *err_str="",ch[32];
     m_text.GetWindowText(textstr);
     if(OpenForcalDll)
     {n=pComForp((char *)(LPCTSTR)textstr,err_str,outl,outd,outc,DllMessage);
      if(n)
      {m_out.ReplaceSel(err_str);
       m_out.ReplaceSel("\r\n编译错误代码:");
       m_out.ReplaceSel(itoa(n,ch,10));
      }
      pExeForp(0,-1,2);
     }
    }

    找到CSimpleOpenFCDlg::DestroyWindow()函数,修改该函数的内容如下,当程序退出时,将执行该函数,以便能够释放动态库:

    BOOL CSimpleOpenFCDlg::DestroyWindow() 
    {
     // TODO: Add your specialized code here and/or call the base class
     if(OpenForcalDll)
     {pFreeDllp();
      FreeLibrary(OpenForcalDll);
     }

     return CDialog::DestroyWindow();
    }

    最后,在文件的末尾添加如下函数实现:

    void outl(long ll)
    {char ch[32];
     pout->ReplaceSel("i:");
     pout->ReplaceSel(ltoa(ll,ch,10));
     pout->ReplaceSel("\r\n");
    }
    void outd(double dd)
    {char ch[32];
     pout->ReplaceSel(gcvt(dd,16,ch));
     pout->ReplaceSel("\r\n");
    }
    void outc(_complex cc)
    {char ch[32];
     pout->ReplaceSel("c:");
     pout->ReplaceSel(gcvt(cc.x,16,ch));
     if(cc.y>=0.0) pout->ReplaceSel("+");
     pout->ReplaceSel(gcvt(cc.y,16,ch));
     pout->ReplaceSel("i\r\n");
    }
    void DllMessage(char *ch) {pout->ReplaceSel(ch); pout->ReplaceSel("\r\n");}

    好了,文件修改完毕,重新编译运行即可。
    为了使程序能够正常运行,需要将OpenForcal.dll和Forcal.dll两个文件放到windows的搜索路径内。


5 使用更多功能的例子  [目录]

    请参考OpenFCtest工程,这是一个使用OpenForcal更多功能的例子。