amzijni.cpp

来自「prolog开发工具」· C++ 代码 · 共 1,850 行 · 第 1/3 页

CPP
1,850
字号
/* Amzi! interface DLL for Java 1.2

   Note - Both Java and Amzi! are Unicode based, so the string
   conversion routines used here are the jstring to Unicode ones,
   not the UTF-8 ones. To build this project, make sure the
   _UNICODE flag is set for the compiler. */

#if defined(_WINDOWS) || defined(_WIN32)
#include <windows.h>
#endif

#include <stdlib.h>
//#include <iostream.h>

#include "amzi.h"
#include "amzi_ls_LogicServer.h"
#include "amzi_ls_LSException.h"
#include "amzijni.h"


/*
#if defined(__GNUC__)
//#if defined(LINUX)
#include <stdlib.h>
#elif defined(__sun)
#include "stdlib.h"
#include <string.h>
#include <iostream.h>
#endif
*/

// Sun's JNI use unsigned short for Unicode characters,
// rather than wchar_t.  So we need both types to see if
// we can get the compiler happy about various arguments.
// Further, because we can't be sure wchar_t is a short,
// we need to have another conversion.  aaarghh.

//#elif defined(LINUX) && defined(_UNICODE)
#if defined(__GNUC__) && defined(_UNICODE)
typedef jchar jCHAR;
#elif defined(__sun) && defined(_UNICODE)
typedef unsigned short jCHAR;
#else
typedef aCHAR jCHAR;
#endif

void ac_to_jc(jCHAR *jc, aCHAR *ac, int len)
{
   for (int i=0; i<=len; i++)
      jc[i] = ac[i];
   jc[len] = 0;
}


aCHAR MsgBuf[MAXMSG];  // A buffer for error messages
jCHAR jcMsgBuf[MAXMSG];

/* This function is used to make a clean copy of a Java string
   that can be used by the LSAPI interface.  It assumes that
   jenv is the pointer to the Java environment. You need to
   delete the string when it is no longer in use. */

aCHAR* JtoC(JNIEnv * jenv, jstring jstr)
{
   const jCHAR *jtmp;
   aCHAR* cstr;
   int    len;

   // Note that GetStringChars does not return
   // a null terminated Unicode string, but rather
   // just an array, that appears null terminated
   // for arrays with an odd length.
   jtmp = jenv->GetStringChars(jstr, NULL);
   len = jenv->GetStringLength(jstr);
   cstr = new aCHAR[len+1];
   for (int i=0; i < len; i++)
      cstr[i] = (aCHAR)jtmp[i];
   cstr[len] = 0;
   jenv->ReleaseStringChars(jstr, jtmp);

   return cstr;
}

/* Another version for non-Unicode strings */

char* JtoCA(JNIEnv * jenv, jstring jstr)
{
   const char *jtmp;
   char* cstr;
   int    len;

   // Note that GetStringChars does not return
   // a null terminated string, but rather
   // just an array.
   jtmp = jenv->GetStringUTFChars(jstr, NULL);
   len = jenv->GetStringUTFLength(jstr);
   cstr = new char[len+1];
   for (int i=0; i < len; i++)
      cstr[i] = (char)jtmp[i];
   cstr[len] = 0;
   jenv->ReleaseStringUTFChars(jstr, jtmp);

   return cstr;
}

/* Get the Engine ID from the Java object. */

#define GET_EID(E)\
   ENGid    E;\
   jclass   jcls;\
   jfieldID jeid;\
   jcls = jenv->GetObjectClass(jobj);\
   jeid = jenv->GetFieldID(jcls, "curEng", "J");\
   E = (ENGid)(jenv->GetLongField(jobj, jeid));


/*
ENGid _get_eid(JNIEnv * jenv, jobject jobj)
{
   ENGid    E;
   jclass   jcls;
   jfieldID jeid;
   jcls = jenv->GetObjectClass(jobj);
   jeid = jenv->GetFieldID(jcls, "curEng", "J");
   E = (ENGid)(jenv->GetIntField(jobj, jeid));
   return E;
}
*/

JExtPred::~JExtPred()
{
   jenv->DeleteGlobalRef(jobj);
   delete[] jmeth_name;
   delete[] jclass_name;
}

JExtPred* EpList = NULL;

// The JNIEnv pointer is not valid from one thread to another.
// So to allow multiple threads, we have all of the exec/call
// functions set this global variable, which is then used
// in extended predicate execution.
JNIEnv *jenv_current;

TF EXPFUNC p_java(void* p)
// AddPred will add as its predicate:
//		AddPred("predname", arity, &::p_java, ptr to the JExtPred block);
{
   jboolean jtf;
   JExtPred* ep = (JExtPred*)p;
   
   ep->jenv = jenv_current;
   jint ji = ep->jenv->GetVersion();
   if (ep->jobj == NULL)
   {
      ep->jcl = ep->jenv->FindClass(ep->jclass_name);
      ep->jmeth = ep->jenv->GetStaticMethodID(ep->jcl, ep->jmeth_name, "()Z");
      if (ep->jmeth == NULL)
         return false;
      jtf = ep->jenv->CallStaticBooleanMethod(ep->jcl, ep->jmeth);
   }
   else
   {
      ep->jcl = ep->jenv->FindClass(ep->jclass_name);
      ep->jmeth = ep->jenv->GetMethodID(ep->jcl, ep->jmeth_name, "()Z");
      if (ep->jmeth == NULL)
         return false;
      jtf = ep->jenv->CallBooleanMethod(ep->jobj, ep->jmeth);
   }

   return (TF)jtf;
}


void amzi_error(JNIEnv * jenv, ENGid curEng, char* lsapif)
{
   char msg[256];
   jclass jclsxcpt;
   jfieldID jeid;
   jmethodID jconstruct;
   int len;
   aCHAR* wmsg;
   jCHAR* jcmsg;
   jstring jmsg;
   jobject jolsxcpt;
   
   // Get the package/class for Amzi! exceptions
   jclsxcpt = jenv->FindClass("amzi/ls/LSException");
   if (jclsxcpt == NULL) goto errorerror;

   // Get the constructor with one string argument
   jconstruct = jenv->GetMethodID(jclsxcpt, "<init>", "(Ljava/lang/String;)V");
   if (jconstruct == NULL) goto errorerror;

   // Create a message and initialize LSException object with it
   sprintf(msg, "Logic Server exception in %s", lsapif);
   len = strlen(msg) + 1;
   if (len > 255) goto errorerror;
   wmsg = new aCHAR[len];
   mbstowcs(wmsg, msg, len);
   jcmsg = new jCHAR[len];
   ac_to_jc(jcmsg, wmsg, len);
   delete[] wmsg;
   jmsg = jenv->NewString(jcmsg, len);
   delete[] jcmsg;
   jolsxcpt = jenv->NewObject(jclsxcpt, jconstruct, jmsg);
   if (jolsxcpt == NULL) goto errorerror;

   jeid = jenv->GetFieldID(jclsxcpt, "curEng", "J");
   jenv->SetLongField(jolsxcpt, jeid, (int)curEng);

   jenv->Throw((_jthrowable*)jolsxcpt);
   return;

errorerror:
   jclass jerror = jenv->FindClass("java/lang/Error");
   jenv->ThrowNew(jerror, "Error processing Amzi! exception");
   return;
}

/* Implementation LSException */
/* -------------------------- */

/*
 * Class:     amzi_ls_LSException
 * Method:    GetType
 * Signature: ()I
 */
extern "C" JNIEXPORT jint JNICALL Java_amzi_ls_LSException_GetType
  (JNIEnv * jenv, jobject jobj)
{
   GET_EID(e);

   ExType type = lsGetExceptType(e);
   return (jint)type;
}

/*
 * Class:     amzi_ls_LSException
 * Method:    GetRC
 * Signature: ()I
 */
extern "C" JNIEXPORT jint JNICALL Java_amzi_ls_LSException_GetRC
  (JNIEnv * jenv, jobject jobj)
{
   GET_EID(e);

   RC rc = lsGetExceptRC(e);
   return (jint)rc;
}

/*
 * Class:     amzi_ls_LSException
 * Method:    GetLineno
 * Signature: ()I
 */
extern "C" JNIEXPORT jint JNICALL Java_amzi_ls_LSException_GetLineno
  (JNIEnv * jenv, jobject jobj)
{
   GET_EID(e);

   int lineno = lsGetExceptLineno(e);
   return (jint)lineno;
}
/*
 * Class:     amzi_ls_LSException
 * Method:    GetMsg
 * Signature: ()Ljava/lang/String;
 */
extern "C" JNIEXPORT jstring JNICALL Java_amzi_ls_LSException_GetMsg
  (JNIEnv * jenv, jobject jobj)
{
   GET_EID(e);
   lsGetExceptMsg(e, MsgBuf, MAXMSG);
   int len = wcslen(MsgBuf);
   ac_to_jc(jcMsgBuf, MsgBuf, len+1);
   jstring jstr = jenv->NewString(jcMsgBuf, len);

   return jstr;
}

/*
 * Class:     amzi_ls_LSException
 * Method:    GetReadFileName
 * Signature: ()Ljava/lang/String;
 */
extern "C" JNIEXPORT jstring JNICALL Java_amzi_ls_LSException_GetReadFileName
  (JNIEnv * jenv, jobject jobj)
{
   GET_EID(e);
   lsGetExceptReadFileName(e, MsgBuf, MAXMSG);
   int len = wcslen(MsgBuf);
   ac_to_jc(jcMsgBuf, MsgBuf, len+1);
   jstring jstr = jenv->NewString(jcMsgBuf, len);

   return jstr;
}

/*
 * Class:     amzi_ls_LSException
 * Method:    GetReadBuffer
 * Signature: ()Ljava/lang/String;
 */
extern "C" JNIEXPORT jstring JNICALL Java_amzi_ls_LSException_GetReadBuffer
  (JNIEnv * jenv, jobject jobj)
{
   GET_EID(e);
   lsGetExceptReadBuffer(e, MsgBuf, MAXMSG);
   int len = wcslen(MsgBuf);
   ac_to_jc(jcMsgBuf, MsgBuf, len+1);
   jstring jstr = jenv->NewString(jcMsgBuf, len);

   return jstr;
}

/*
 * Class:     amzi_ls_LSException
 * Method:    GetCallStack
 * Signature: ()Ljava/lang/String;
 */
extern "C" JNIEXPORT jstring JNICALL Java_amzi_ls_LSException_GetCallStack
  (JNIEnv * jenv, jobject jobj)
{
   GET_EID(e);
   lsGetExceptCallStack(e, MsgBuf, MAXMSG);
   int len = wcslen(MsgBuf);
   ac_to_jc(jcMsgBuf, MsgBuf, len+1);
   jstring jstr = jenv->NewString(jcMsgBuf, len);

   return jstr;
}


/* Implementation LogicServer */
/* -------------------------- */

/*
 * Class:     amzi_ls_LogicServer
 * Method:    Init
 * Signature: (Ljava/lang/String;)V
 */
extern "C" JNIEXPORT void JNICALL Java_amzi_ls_LogicServer_Init
  (JNIEnv * jenv, jobject jobj, jstring jstr)
{
   ENGid curEng;
   RC    rc;
   jclass   jcls;
   jfieldID jeid;
   aCHAR* ininame;
   
//   EpList = NULL;   // Initialize extended predicates

   ininame = JtoC(jenv, jstr);
   rc = lsInit(&curEng, ininame);
   delete[] ininame;

   if (curEng == NULL)
   {
      jclass jerror = jenv->FindClass("java/lang/OutOfMemoryError");
      jenv->ThrowNew(jerror, "Unable to allocate new Logic Server");
   }

   if (rc != OK)
      amzi_error(jenv, curEng, "Init");

   jcls = jenv->GetObjectClass(jobj);
   jeid = jenv->GetFieldID(jcls, "curEng", "J");
   jenv->SetLongField(jobj, jeid, (int)curEng);

   return;
}

/*
 * Class:     amzi_ls_LogicServer
 * Method:    Init2
 * Signature: (Ljava/lang/String;)V
 */
extern "C" JNIEXPORT void JNICALL Java_amzi_ls_LogicServer_Init2
  (JNIEnv * jenv, jobject jobj, jstring jstr)
{
   ENGid curEng;
   RC    rc;
   jclass   jcls;
   jfieldID jeid;
   aCHAR* inistr;

//   EpList = NULL;    // Initialize extended predicates.
   
   inistr = JtoC(jenv, jstr);
   rc = lsInit2(&curEng, inistr);
   delete[] inistr;

   if (curEng == NULL)
   {
      jclass jerror = jenv->FindClass("java/lang/OutOfMemoryError");
      jenv->ThrowNew(jerror, "Unable to allocate new Logic Server");
   }

   if (rc != OK)
      amzi_error(jenv, curEng, "Init2");

   jcls = jenv->GetObjectClass(jobj);
   jeid = jenv->GetFieldID(jcls, "curEng", "J");
   jenv->SetLongField(jobj, jeid, (int)curEng);

   return;
}

/*
 * Class:     amzi_ls_LogicServer
 * Method:    InitLSX
 * Signature: (J)V
 */
extern "C" JNIEXPORT void JNICALL Java_amzi_ls_LogicServer_InitLSX
  (JNIEnv * jenv, jobject jobj, jlong ptr)
{
   RC  rc;

   GET_EID(e);
   rc = lsInitLSX(e, (void*)ptr);
   if (rc != OK)
      amzi_error(jenv, e, "InitLSX");

   return;
}

/*
 * Class:     amzi_ls_LogicServer
 * Method:    AddPred-8
 * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V
 */
JNIEXPORT void JNICALL Java_amzi_ls_LogicServer_AddJPred
  (JNIEnv * jenv, jobject jobj, jstring jfunctor, jint arity,
   jstring jcl_name, jstring jmethod_name, jobject jmethobj,
   jlong lseng)
{
//FILE* log = fopen("d:\\temp\\a5jlog.txt", "w");
//fprintf(log, "Log file\n");

   RC  rc;
   aCHAR* functor;
   char* method_name;
   char* cl_name;
   JExtPred* ep;
   jobject jgobj;

//fprintf(log, "0\n"); fflush(log);
   GET_EID(e);

//fprintf(log, "1\n"); fflush(log);
   ep = new JExtPred();
   ep->jenv = jenv;

//fprintf(log, "2\n"); fflush(log);
   if (jmethobj == NULL)
      ep->jobj = NULL;
   else
   {
      jgobj = jenv->NewGlobalRef(jmethobj);
      ep->jobj = jgobj;
   }

   ep->lseng = lseng;
   
//fprintf(log, "3\n"); fflush(log);
   // Find the class for the extended predicate
   cl_name = JtoCA(jenv, jcl_name);
   ep->jclass_name = cl_name;
//   ep->jcl = jenv->FindClass(cl_name);
//   ep->jcl = jenv->FindClass(cl_name);
//   if (ep->jcl == NULL)
//      amzi_error(jenv, e, "AddPred");
//   delete[] cl_name;

//fprintf(log, "4\n"); fflush(log);
   // And the method
   method_name = JtoCA(jenv, jmethod_name);
   ep->jmeth_name = method_name;
//   ep->jmeth = jenv->GetMethodID(ep->jcl, method_name, "()Z");
//   if (ep->jmeth == NULL)
//      amzi_error(jenv, e, "AddPred");
//   delete[] method_name;

//fprintf(log, "5\n"); fflush(log);
   // thread linked list
   ep->pnext = EpList;
   EpList = ep;

//fprintf(log, "6\n"); fflush(log);
   functor = JtoC(jenv, jfunctor);
   rc = lsAddPred(e, functor, (ARITY)arity, &::p_java, (VOIDptr)ep);
   if (rc != OK)
      amzi_error(jenv, e, "AddPred");
   delete[] functor;

//fprintf(log, "done"); fclose(log);
   return;
}

/* This should become obsolete in 6.1
 * Class:     amzi_ls_LogicServer
 * Method:    AddPred-7
 * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V
 */
/*
extern "C" JNIEXPORT void JNICALL Java_amzi_ls_LogicServer_AddPred
  (JNIEnv * jenv, jobject jobj, jstring jfunctor, jint arity,
   jstring jcl_name, jstring jmethod_name, jobject jmethobj)
{
//FILE* log = fopen("d:\\temp\\a5jlog.txt", "w");
//fprintf(log, "Log file\n");

   RC  rc;
   aCHAR* functor;
   char* method_name;
   char* cl_name;
   JExtPred* ep;
   jobject jgobj;

//fprintf(log, "0\n"); fflush(log);
   GET_EID(e);

//fprintf(log, "1\n"); fflush(log);
   ep = new JExtPred();
   ep->jenv = jenv;

//fprintf(log, "2\n"); fflush(log);
   jgobj = jenv->NewGlobalRef(jmethobj);
   ep->jobj = jgobj;
   
//fprintf(log, "3\n"); fflush(log);
   // Find the class for the extended predicate
   cl_name = JtoCA(jenv, jcl_name);
//   ep->jcl = jenv->FindClass(cl_name);
   ep->jcl = jenv->FindClass(cl_name);
   if (ep->jcl == NULL)
      amzi_error(jenv, e, "AddPred");
   delete[] cl_name;

//fprintf(log, "4\n"); fflush(log);
   // And the method
   method_name = JtoCA(jenv, jmethod_name);
   ep->jmeth_name = method_name;
   ep->jmeth = jenv->GetMethodID(ep->jcl, method_name, "()Z");
   if (ep->jmeth == NULL)
      amzi_error(jenv, e, "AddPred");
//   delete[] method_name;

//fprintf(log, "5\n"); fflush(log);
   // thread linked list
   ep->pnext = EpList;
   EpList = ep;

//fprintf(log, "6\n"); fflush(log);
   functor = JtoC(jenv, jfunctor);
   rc = lsAddPred(e, functor, (ARITY)arity, &::p_java, (VOIDptr)ep);
   if (rc != OK)
      amzi_error(jenv, e, "AddPred");

//fprintf(log, "done"); fclose(log);
   return;
}
*/

/*
 * Class:     amzi_ls_LogicServer
 * Method:    AddLSX
 * Signature: (Ljava/lang/String;J)V
 */
extern "C" JNIEXPORT void JNICALL Java_amzi_ls_LogicServer_AddLSX
  (JNIEnv * jenv, jobject jobj, jstring jlsxname, jlong ptr)
{
   RC  rc;
   aCHAR* lsxname;

   GET_EID(e);
   lsxname = JtoC(jenv, jlsxname);
   rc = lsAddLSX(e, lsxname, (void *)ptr);
   delete[] lsxname;
   if (rc != OK)
      amzi_error(jenv, e, "AddLSX");

   return;
}

/*
 * Class:     amzi_ls_LogicServer
 * Method:    Load
 * Signature: (Ljava/lang/String;)V
 */
extern "C" JNIEXPORT void JNICALL Java_amzi_ls_LogicServer_Load
  (JNIEnv * jenv, jobject jobj, jstring jstr)
{
   RC     rc;
   aCHAR* xplname;

   GET_EID(e);
   //ENGid e;
   //e = _get_eid(jenv, jobj);
   xplname = JtoC(jenv, jstr);
   rc = lsLoad(e, xplname);
   delete[] xplname;
   if (rc != OK)
      amzi_error(jenv, e, "Load");

   return;
}


/*
 * Class:     amzi_ls_LogicServer
 * Method:    Main
 * Signature: ()Z
 */
extern "C" JNIEXPORT jboolean JNICALL Java_amzi_ls_LogicServer_Main
  (JNIEnv * jenv, jobject jobj)
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?