📄 clipsmfc_old.cpp
字号:
/*
clipsMFC.cpp : implementation file for a CLIPS Wrapper class using MFC
Notes: Allows encapsulation of the 'C' interface for CLIPS. Also adds
enhanced parameter/error checking, and simplifies the
housekeeping that is needed in the main application as a lot of
this is handled by class instance variables. It should also be
relatively easy to expand this class to cover more of the
CLIPS interface than I initially used.
** there are a lot of definitions in the first portion of the
header file, please review these settings and adjust to suit the
needs of YOUR project.
Author(s): Mark Tomlinson, Michael Giordano
Version: 2.0
Revision WHO Date WHY
--------------------------------------------------
1.1 mdt 5/4/96 instance & dynaload
1.5 mdt 6/19/97 Added Build()
1.6 mdt 9/29/97 added createfact
1.7 mjg 1/21/98 added ODBC Query
1.8 mjg 1/29/98 added UserDefined router support
1.9 mdt 1/31/98 minor bug fixes, mods to UserDefined routers
2.0 mdt/mjg 2/21/98 minor bug in WriteFactSlot, added UserFunctions
2.2 mdt 7/15/98 Major overhaul of route buffers
2.3 sj 5/12/99 AddResetFunction()
3.0 mdt 5/16/99 First major overhaul in many moons
fixed many little problems and
cleaned up code (such as using CLIPS
pointer validation routines), all
references to external CString* converted
to CString & and added the following:
PeriodicCleanup()
*/
#ifndef _DEBUG
#pragma optimize("",off)
#pragma optimize("q",off)
#endif
#define NON_VERBOSE_LOG 1
#define DEF_CB_PRIORITY 1
//stream i/o
#include <iostream.h> //ios
#include <fstream.h> //ofstream
#include <direct.h>
#ifndef __AFX_H__
#include <afx.h>
#endif
#ifndef __AFXCOLL_H__
#include <afxcoll.h>
#endif
#define __defc
//default loop count
int Defcount;
//running flag
bool Running;
//error log file
char ErrorLog[_MAX_PATH] = "";
//macro used to check GPA() return values
#define CHKFNPTR(p,s) if (p == NULL) { \
char t_buf[100]; \
sprintf(t_buf,"Unable to locate CLIPS entry point for function: %s",s); \
::MessageBox(NULL,t_buf,"CLIPSWrap::GetProcAddress",MB_OK); \
return FALSE; }
//macro to load a given proc address from CLIPS DLL
#define GPA(p,t,n) p = (t) GetProcAddress(m_hLib,n); \
CHKFNPTR(p,n)
/////////////////////////////////////////////////////////////////////////////
// exported functions for DLL suppport/callbacks
//include for all clips defs
extern "C" {
#include <dynclips.h>
}
//class definition
#include <clipsmfc.h>
#ifdef USE_ODBC
//Header files for ODBC Query
#include <afxdb.h>
#include "rsvarcol.h" //Class definition for CVarRecordset
#endif
extern "C" {
/* some global variables */
//array of pointer to the string buffers for memory routes
//CObjArray
CStringArray* pRoutes[NUMROUTES];
CString* pRteNames[NUMROUTES];
//string arrays to manage lists of file routes
CStringArray* FileRoutes;
CStringArray* FileNames;
}
//prototype for generic CB function which can be set to fire periodically
void far (*CBfunctPtr)(bool);
/*
This function handles out of memory conditions for CLIPS, this is a callback
from CLIPS.
*/
extern "C" int DllExport ReportMemoryProblems(unsigned long p)
{
//!!! (dl_PeriodicCleanup)(TRUE, TRUE);
return 0;
}
/*
This function captures which routes we will handle, this is a callback
from CLIPS.
*/
extern "C" int DllExport captureQuery(char *router)
{
/*
If the router comes from stdout, stdin, wclips, wdisplay, ...,
then we will accept the output. Otherwise, pass the buck onto
someone else. This could be done using a string container class.
*/
//return true if we handle this route, and false if not.
if(IsDefaultRouter(router)) {
return TRUE;
}
return (GetRouteNum(0,router) != -1);
}
/*
This function actually handles what to do with the routed
information. This is a callback from CLIPS.
*/
extern "C" int DllExport capturePrint(char far* router, char far* str)
{
static CString message;
CString hold;
CString Route;
int rnum = 0, i, n = -1;
if(strlen(ErrorLog) == 0) {
//get Windows directory - this is where we want to put it
memset(ErrorLog,0,256);
GetWindowsDirectory(ErrorLog,255);
strcat(ErrorLog,"\\CLIPSDLL.ERR");
}
// Dump all routes to the file CLIPSDLL.ERR
// if not handled in another way, in this code
// the "other way" is to copy the string into
// an array which was initialized elsewhere.
// since CLIPS does not actually format the route
// data you could add a routine to collect all the
// output data on a given route until a CRLF was recieved
// thus building a single string of output.
//(ex-) (str-cat ?item1 ?item2 ?item3 ... "some text" ...)
// (printout wwhatever ..........)
bool fHandled = false;
hold = str;
// loop in case there is more than 1 buffer/route
while ((rnum = GetRouteNum(rnum,router)) != -1) {
if(pRoutes[rnum] != NULL) {
pRoutes[rnum]->Add(str);
fHandled = true;
}
++rnum;
}
Route = router;
if (FileRoutes!=NULL) {
for(i = 0; i < FileRoutes->GetSize(); i++) {
if(FileRoutes->GetAt(i) == Route) {
n = i;
}
if(n != -1) {
ofstream *ofFile;
ofFile = new ofstream(FileNames->GetAt(i),ios::out | ios::app | ios::binary);
long i = 0;
(*ofFile) << hold;
#if VERBOSE_LOG
(*ofFile) << "\r\n";
#endif
fHandled = true;
delete ofFile;
}
}
}
if(!fHandled) {
// create the error log for unhandled routes
ofstream *ofError;
ofError = new ofstream(ErrorLog,ios::out | ios::app | ios::binary);
//is it a EOL situation?
if((strncmp((LPCSTR)hold,"\r\n",2)!= 0) &&
(strncmp((LPCSTR)hold,"\r",1)!= 0) &&
(strncmp((LPCSTR)hold,"\n",1)!= 0)) {
if(message.GetLength() > MBUFSIZE) { //don't let it get too big
(*ofError) << message;
#if VERBOSE_LOG
(*ofError) << "\r\n";
#endif
message.Empty();
}
if(message.GetLength() == 0) {
message += "\r\n";
message += "Msg from ";
message += (char *)router;
message += ": ";
}
message += hold;
}
else {
(*ofError) << message;
#if VERBOSE_LOG
(*ofError) << "\r\n";
#endif
message.Empty();
}
delete ofError;
}
return TRUE;
} //end of extern 'c' declaration block
//return ordinal number of specified route
int GetRouteNum(int start, const char far* route)
{
int rnum = -1;
for(int i = start; i < NUMROUTES; i++) {
if(pRteNames[i] != NULL) {
if(pRteNames[i]->CompareNoCase(route) == 0) {
rnum = i;
break;
}
}
}
return rnum;
}
//check to see if router is a system defualt router name
bool IsDefaultRouter(const char * route)
{
if((_stricmp(route, "stdout")==0) ||
(_stricmp(route, "werror")==0) ||
(_stricmp(route, "wclips")==0) ||
(_stricmp(route, "wdisplay")==0) ||
(_stricmp(route, "wdialog")==0) ||
(_stricmp(route, "wtrace")==0) ||
(_stricmp(route, "wagenda")==0) ||
(_stricmp(route, "wwarning")==0)) {
return true;
}
return false;
}
/////////////////////////////////////////////////////////////////////////////
// CCLIPSWrap - all class implementation functions
//constructor
//note: construction does NOT load the DLL
CCLIPSWrap::CCLIPSWrap(int count)
: factPtr (NULL), rulePtr (NULL), modulePtr (NULL), globalPtr (NULL),
instancePtr (NULL), classPtr (NULL), m_hLib (NULL)
{
int i;
Defcount = count;
Running = false;
m_fClipsInit = false;
CLEARMBUF
for(i = 0; i < NUMROUTES; i++) {
pRoutes[i] = NULL;
pRteNames[i] = NULL;
}
FileRoutes = NULL;
FileNames = NULL;
CBfunctPtr = NULL;
factPtr = NULL;
modulePtr = NULL;
rulePtr = NULL;
globalPtr = NULL;
instancePtr = NULL;
classPtr = NULL;
activationPtr = NULL;
agendaPtr = NULL;
templatePtr = NULL;
insSlotPtr = NULL;
tempSlotPtr = NULL;
fastLoad = NULL;
fastSave = NULL;
}
//destructor
//cleanup memory
CCLIPSWrap::~CCLIPSWrap(void)
{
CBfunctPtr = NULL;
factPtr = NULL;
modulePtr = NULL;
rulePtr = NULL;
globalPtr = NULL;
instancePtr = NULL;
classPtr = NULL;
activationPtr = NULL;
agendaPtr = NULL;
templatePtr = NULL;
insSlotPtr = NULL;
tempSlotPtr = NULL;
fastLoad = NULL;
fastSave = NULL;
if(FileRoutes != NULL) {
delete FileRoutes;
FileRoutes = NULL;
}
if(FileNames != NULL) {
delete FileNames;
FileNames = NULL;
}
//the route buffers in memory will not be deleted
//since we did not allocate them in this class
for(int i = 0; i < NUMROUTES; i++) {
if(pRteNames[i] != NULL) {
delete pRteNames[i];
pRteNames[i] = NULL;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// virtual functions
/***************************************************************************
Function : CCLIPSWrap::SetErrorLog(CString& filename)
Author : Mark Tomlinson
Desc. : set filename & path for error route log filename
Returns : none
****************************************************************************/
void CCLIPSWrap::SetErrorLog(CString& filename)
{
strcpy(ErrorLog,(LPCSTR)(filename));
}
/***************************************************************************
Function : CCLIPSWrap::SetMsgLoopCBfn(void far (*func_ptr)(void))
Author : Mark Tomlinson
Desc. : set callback function which be invoked during msgpump loops
Returns : none
****************************************************************************/
void CCLIPSWrap::SetMsgLoopCBfn(void far (*func_ptr)(bool))
{
CBfunctPtr = func_ptr;
}
/****************************************************************************
Function : CCLIPSWrap::CLIPSInit(void)
Author : Mark Tomlinson
Desc. : Accessor function to CLIPS InitilizeCLIPS(), also will
load the DLL into memory, get procedure entry points &
initialize the default capture router.
Returns : true on success, false if it fails.
****************************************************************************/
bool CCLIPSWrap::CLIPSInit(void)
{
if(m_fClipsInit)
return true;
//now decide which DLL to load...
if(m_hLib == NULL) {
#ifdef WIN32
m_hLib = LoadLibrary ("clips.dll");
#else
m_hLib = LoadLibrary ("clipsdll.dll");
#endif
}
if(m_hLib == NULL)
return false;
if(LoadDllReferences() == false) {
//unload the library
FreeLibrary(m_hLib);
m_hLib = NULL;
return false;
}
//call init clips
(dl_InitializeCLIPS)();
//set message pump callback function to prevent a hang
//of the system when CLIPS is doing lengthy processing
//not exactly needed in WIN32 - essential in WIN16
#ifndef WIN32
(dl_AddPeriodicFunction)("msgpump",MsgLoopProc,1);
#endif
//set out of memory handler function
(dl_SetOutOfMemoryFunction)((unsigned long)ReportMemoryProblems);
//tell CLIPS to be quiet while loading files
(dl_SetPrintWhileLoading)(false);
// add router to handle output from DLL functions, (if any), although
// you are best to assume some output so as not to overwrite the
// windows desktop with TTY output from the DLL. Then return.
if((dl_AddRouter)("capture", 20, (int (*)(char *))captureQuery, (int (*)(char *,char *))capturePrint, NULL, NULL, NULL)) {
m_fClipsInit = true;
return true;
}
//failed
return false;
}
/***************************************************************************
Function : CCLIPSWrap::CLIPSReset(void)
Author : Mark Tomlinson
Desc. : Accessor function for CLIPS Reset
Returns : true on success, false on error
****************************************************************************/
bool CCLIPSWrap::CLIPSReset(void)
{
INITCHK(false)
(dl_Reset)();
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -