📄 clipslibwrap_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()
3.1 mdt 10/27/00 Cleanup for completeness. Added multifield
support to:
WriteFactSlot, CLIPSDirectGetSlot,
DirectPutSlot & ReadFactSlot
as a part of this StringToMultifield was
added.
fixed a bug in CLIPSGetNextInstanceInClass
that prevented you from passing in a Ptr
rather than using the one in the wrapper. You
can now use either the default or one you provide.
Same for CLIPSGetNextActivation.
Same for CLIPSGetNextDefclass.
Same for CLIPSNextFact
Modified CLIPSNextFactString to support this
behavior as well, used default parameter so that
behavior need not break existing code.
Ditto for CLIPSFactString
Ditto for CLIPSCreateRawInstance
Ditto for CLIPSGetNextDefglobal
Ditto for CLIPSGetInstancePPForm
Cleaned up the code in CLIPSAgenda -- had holdover
code from the early days of UserRouters.
Cleanup CLIPSWatch & CLIPSUnwatch
Ditto CLIPSMatches & fixed it to work with latest
DLL build (where Matches takes two params).
Ditto CLIPSUndefglobal
Added:
GetInstanceSlot
GetInstanceSlotType
GetSlotCount
GetInstanceSlotName
Added a lot more of the CLIPS struct definitions
to dynclips.h to support the above functions.
Synchronized the library and dynamic load versions.
*/
#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 <clips.h>
}
//class definition
#include "clipslibwrap.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)
{
//you may want to add this in here ---> (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,"\\CLIPSOCX.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)
{
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;
//call init clips
InitializeEnvironment();
//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
AddPeriodicFunction("msgpump",MsgLoopProc,1);
#endif
//set out of memory handler function
SetOutOfMemoryFunction(ReportMemoryProblems);
//tell CLIPS to be quiet while loading files
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(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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -