/* $Id: jpl.c,v 1.1 2004-08-27 20:27:32 vsc Exp $ Part of JPL -- SWI-Prolog/Java interface Author: Paul Singleton, Fred Dushin and Jan Wielemaker E-mail: paul@jbgb.com WWW: http://www.swi-prolog.org Copyright (C): 1985-2004, Paul Singleton This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // this source file (jpl.c) combines my Prolog-calls-Java stuff (mostly prefixed 'JNI' or 'jni' here) // with my adaptation of Fred Dushin's Java-calls-Prolog stuff (mostly prefixed 'JPL' or 'jpl' here) // recent fixes: // * using PL_get_pointer(), PL_put_pointer() consistently (?) // // still to do: // * make it completely thread-safe // (both to multiple Prolog (engine-enabled) threads and to multiple Java threads) // * suss JVM 'abort' and 'exit' handling, and 'vfprintf' redirection // * figure out why Java native methods have "Class: jpl_fli_PL" (and not jpl_fli_Prolog) // * rationalise initialisation; perhaps support startup from C? // update this to distinguish releases of this C library: #define JPL_C_LIB_VERSION "3.0.4-alpha" #define JPL_C_LIB_VERSION_MAJOR 3 #define JPL_C_LIB_VERSION_MINOR 0 #define JPL_C_LIB_VERSION_PATCH 4 #define JPL_C_LIB_VERSION_STATUS "alpha" #define DEBUG(n, g) ((void)0) //=== includes ===================================================================================== #ifdef WIN32 // OS-specific header (SWI-Prolog FLI and Java Invocation API both seem to need this): #include #endif // SWI-Prolog headers: #if IN_YAP #include #else #include #include #endif // Java Native Interface and Invocation Interface header: #include // ANSI/ISO C library header (?): #include #include #include #include // POSIX 'pthreads' headers (initially for JPL's Prolog engine pool, useful for locking generally?): #include #include int jni_create_default_jvm(void); install_t jpl_install(void); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_get_1default_1init_1args(JNIEnv *, jclass); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_set_1default_1init_1args(JNIEnv *, jclass, jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_get_1actual_1init_1args(JNIEnv *,jclass); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_initialise(JNIEnv *,jclass); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_halt(JNIEnv *,jclass,jint); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1term_1ref(JNIEnv *,jclass); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1term_1refs(JNIEnv *,jclass,jint); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_copy_1term_1ref(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_reset_1term_1refs(JNIEnv *, jclass,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1atom(JNIEnv *,jclass,jstring); JNIEXPORT jstring JNICALL Java_jpl_fli_Prolog_atom_1chars(JNIEnv *,jclass,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1functor(JNIEnv *,jclass,jobject,jint); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_functor_1name(JNIEnv *,jclass,jobject); JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_functor_1arity(JNIEnv *,jclass,jobject); JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_term_1type(JNIEnv *env,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1variable(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1atom(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1integer(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1float(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1compound(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1functor(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1list(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1atomic(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1number(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1atom(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1atom(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1atom_1chars(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1string_1chars(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1chars(JNIEnv *,jclass,jobject,jobject,jint); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1list_1chars(JNIEnv *,jclass,jobject,jobject,jint); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1integer(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1pointer(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1float(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1jref(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1jboolean(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1jpl_1term(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1functor(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1name_1arity(JNIEnv *,jclass,jobject,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1module(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1arg(JNIEnv *,jclass,jint,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1list(JNIEnv *,jclass,jobject,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1head(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1tail(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1nil(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1variable(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1atom(JNIEnv *,jclass,jobject,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1atom_1chars(JNIEnv *,jclass,jobject,jstring); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1list_1chars(JNIEnv *,jclass,jobject,jstring); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1integer(JNIEnv *,jclass,jobject,jlong); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1pointer(JNIEnv *,jclass,jobject,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1float(JNIEnv *,jclass,jobject,jdouble); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1functor(JNIEnv *,jclass,jobject,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1list(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1nil(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1term(JNIEnv *,jclass,jobject,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1jref(JNIEnv *,jclass,jobject,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1jboolean(JNIEnv *,jclass,jobject,jboolean); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1jvoid(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_cons_1functor_1v(JNIEnv *,jclass,jobject,jobject,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_cons_1list(JNIEnv *,jclass,jobject,jobject,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_open_1foreign_1frame(JNIEnv *,jclass); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_close_1foreign_1frame(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_discard_1foreign_1frame(JNIEnv *,jclass,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_pred(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_predicate(JNIEnv *,jclass,jstring,jint,jstring); JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_predicate_1info(JNIEnv *,jclass,jobject,jobject,jobject,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_open_1query(JNIEnv *,jclass,jobject,jint,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_next_1solution(JNIEnv *,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_cut_1query(JNIEnv *env,jclass,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_close_1query(JNIEnv *,jclass,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_call_1predicate(JNIEnv *,jclass,jobject,jint,jobject,jobject); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_call(JNIEnv *,jclass,jobject,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_exception(JNIEnv *,jclass,jobject); JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_compare(JNIEnv *,jclass,jobject,jobject); JNIEXPORT void JNICALL Java_jpl_fli_Prolog_unregister_1atom(JNIEnv *,jclass,jobject); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1module(JNIEnv *,jclass,jobject); JNIEXPORT int JNICALL Java_jpl_fli_Prolog_action_1abort(JNIEnv *,jclass); JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_thread_1self(JNIEnv *,jclass); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_attach_1pool_1engine(JNIEnv *,jclass); JNIEXPORT int JNICALL Java_jpl_fli_Prolog_attach_1engine(JNIEnv *,jclass,jobject); JNIEXPORT int JNICALL Java_jpl_fli_Prolog_pool_1engine_1id(JNIEnv *env,jclass,jobject); JNIEXPORT int JNICALL Java_jpl_fli_Prolog_release_1pool_1engine(JNIEnv *,jclass); JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_current_1engine_1is_1pool(JNIEnv *env,jclass); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_current_1engine(JNIEnv *env,jclass); JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_get_1c_1lib_1version(JNIEnv *,jclass); //=== JNI constants ================================================================================ #define JNI_MIN_JCHAR 0 #define JNI_MAX_JCHAR 65535 #define JNI_MIN_JBYTE -128 #define JNI_MAX_JBYTE 127 #define JNI_MIN_JSHORT -32768 #define JNI_MAX_JSHORT 32767 #define JNI_XPUT_VOID 0 #define JNI_XPUT_BOOLEAN 1 #define JNI_XPUT_BYTE 2 #define JNI_XPUT_CHAR 3 #define JNI_XPUT_SHORT 4 #define JNI_XPUT_INT 5 #define JNI_XPUT_LONG 6 #define JNI_XPUT_FLOAT 7 #define JNI_XPUT_DOUBLE 8 #define JNI_XPUT_FLOAT_TO_DOUBLE 9 #define JNI_XPUT_LONG_TO_FLOAT 10 #define JNI_XPUT_LONG_TO_DOUBLE 11 #define JNI_XPUT_REF 12 #define JNI_XPUT_ATOM 13 #define JNI_XPUT_JVALUEP 14 #define JNI_XPUT_JVALUE 15 // JNI "hashed refs" constants #define JNI_HR_LOAD_FACTOR 0.75 // jni_hr_add() return codes: #define JNI_HR_ADD_FAIL -1 #define JNI_HR_ADD_NEW 0 #define JNI_HR_ADD_OLD 1 //=== JPL constants ================================================================================ // legit values for jpl_status_jpl_ini and jpl_status_pvm_ini #define JPL_INIT_RAW 101 #define JPL_INIT_PVM_MAYBE 102 #define JPL_INIT_OK 103 #define JPL_INIT_JPL_FAILED 104 #define JPL_INIT_PVM_FAILED 105 #define JPL_MAX_POOL_ENGINES 10 /* max pooled Prolog engines */ #define JPL_INITIAL_POOL_ENGINES 1 /* initially created ones */ //=== JNI Prolog<->Java conversion macros ========================================================== // JNI (Prolog-calls-Java) conversion macros; mainly used in jni_{func|void}_{0|1|2|3|4}_plc // for re-entrancy, ensure that any variables which they use are declared dynamically // (e.g. or i.e. are local to the host function) // beware of evaluating *expressions* passed as actual parameters more than once #define JNI_term_to_jboolean(T,JB) \ ( PL_get_functor((T),&fn) \ && fn==JNI_functor_at_1 \ ? ( ( a1=PL_new_term_ref(), \ PL_get_arg(1,(T),a1) \ ) \ && PL_get_atom(a1,&a) \ ? ( a==JNI_atom_false \ ? ( (JB)=0, TRUE) \ : ( a==JNI_atom_true \ ? ( (JB)=1, TRUE) \ : FALSE \ ) \ ) \ : FALSE \ ) \ : FALSE \ ) #define JNI_term_to_jchar(T,J) \ ( PL_get_integer((T),&(J)) \ && (J) >= JNI_MIN_JCHAR \ && (J) <= JNI_MAX_JCHAR \ ) #define JNI_term_to_jbyte(T,J) \ ( PL_get_integer((T),&(J)) \ && (J) >= JNI_MIN_JBYTE \ && (J) <= JNI_MAX_JBYTE \ ) #define JNI_term_to_jshort(T,J) \ ( PL_get_integer((T),&(J)) \ && (J) >= JNI_MIN_JSHORT \ && (J) <= JNI_MAX_JSHORT \ ) #define JNI_term_to_jint(T,J) \ ( PL_get_integer((T),&(J)) \ ) #define JNI_term_to_non_neg_jint(T,J) \ ( PL_get_integer((T),&(J)) \ && (J) >= 0 \ ) #define JNI_term_to_jlong(T,J) \ ( PL_get_integer((T),&i) \ ? ( (J)=(jlong)i, TRUE) \ : JNI_jlong2_to_jlong(T,(J)) \ ) #define JNI_jlong2_to_jlong(T,J) \ ( PL_get_functor((T),&fn) \ && fn==JNI_functor_jlong_2 \ ? ( ( a1=PL_new_term_ref(), \ PL_get_arg(1,(T),a1) \ ) \ && ( a2=PL_new_term_ref(), \ PL_get_arg(2,(T),a2) \ ) \ && PL_get_integer(a1,&xhi) \ && PL_get_integer(a2,&xlo) \ ? ( ((int*)&(J))[1]=xhi, \ ((int*)&(J))[0]=xlo, \ TRUE \ ) \ : FALSE \ ) \ : FALSE \ ) #define JNI_term_to_jfloat(T,J) \ ( PL_get_float((T),&(J)) \ ? TRUE \ : ( PL_get_integer((T),&i) \ ? ( (J)=(jfloat)i, TRUE) \ : ( JNI_jlong2_to_jlong((T),jl) \ ? ( (J)=(jfloat)jl, TRUE) \ : FALSE \ ) \ ) \ ) #define JNI_term_to_jdouble(T,J) \ ( PL_get_float((T),&(J)) \ ? TRUE \ : ( PL_get_integer((T),&i) \ ? ( (J)=(jdouble)i, TRUE) \ : ( JNI_jlong2_to_jlong((T),jl) \ ? ( (J)=(jdouble)jl, TRUE) \ : FALSE \ ) \ ) \ ) #define JNI_term_to_jfieldID(T,J) \ ( PL_get_functor((T),&fn) \ && fn==JNI_functor_jfieldID_1 \ && ( a1=PL_new_term_ref(), \ PL_get_arg(1,(T),a1) \ ) \ && PL_get_pointer(a1,(void**)&(J)) \ ) #define JNI_term_to_jmethodID(T,J) \ ( PL_get_functor((T),&fn) \ && fn==JNI_functor_jmethodID_1 \ && ( a1=PL_new_term_ref(), \ PL_get_arg(1,(T),a1) \ ) \ && PL_get_pointer(a1,(void**)&(J)) \ ) // converts: // atom -> String // @(null) -> NULL // @(tag) -> obj // (else fails) // #define JNI_term_to_ref(T,J) \ ( PL_get_atom_chars((T),&cp) \ ? ((J)=(*env)->NewStringUTF(env,cp))!=NULL \ : PL_get_functor((T),&fn) \ && fn==JNI_functor_at_1 \ && ( a1=PL_new_term_ref(), \ PL_get_arg(1,(T),a1) \ ) \ && PL_get_atom(a1,&a) \ && ( a==JNI_atom_null \ ? ( (J)=0, TRUE) \ : jni_tag_to_iref(a,(int*)&(J)) \ ) \ ) // converts: // atom -> String // @tag -> obj // (else fails) // stricter than JNI_term_to_ref(T,J) // #define JNI_term_to_jobject(T,J) \ ( PL_get_atom_chars((T),&cp) \ ? ((J)=(*env)->NewStringUTF(env,cp))!=NULL \ : PL_get_functor((T),&fn) \ && fn==JNI_functor_at_1 \ && ( a1=PL_new_term_ref(), \ PL_get_arg(1,(T),a1) \ ) \ && PL_get_atom(a1,&a) \ && a!=JNI_atom_null \ && jni_tag_to_iref(a,(int*)&(J)) \ ) // for now, these specific test-and-convert macros // are merely mapped to their nearest ancestor... #define JNI_term_to_jclass(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_throwable_jclass(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_non_array_jclass(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_throwable_jobject(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_jstring(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_object_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_boolean_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_byte_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_char_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_short_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_int_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_long_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_float_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_double_jarray(T,J) JNI_term_to_jobject(T,J) #define JNI_term_to_jbuf(T,J,TP) \ ( PL_get_functor((T),&fn) \ && fn==JNI_functor_jbuf_2 \ && ( a2=PL_new_term_ref(), \ PL_get_arg(2,(T),a2) \ ) \ && PL_get_atom(a2,&a) \ && a==(TP) \ && ( a1=PL_new_term_ref(), \ PL_get_arg(1,(T),a1) \ ) \ && PL_get_pointer(a1,(void**)&(J)) \ ) #define JNI_term_to_charP(T,J) \ PL_get_atom_chars((T),&(J)) #define JNI_term_to_pointer(T,J) \ PL_get_pointer((T),(void**)&(J)) // JNI Java-to-Prolog conversion macros: #define JNI_unify_void(T) \ PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_at_1, \ PL_ATOM, JNI_atom_void \ ) #define JNI_unify_false(T) \ PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_at_1, \ PL_ATOM, JNI_atom_false \ ) #define JNI_unify_true(T) \ PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_at_1, \ PL_ATOM, JNI_atom_true \ ) #define JNI_jboolean_to_term(J,T) \ ( (J)==0 \ ? JNI_unify_false((T)) \ : JNI_unify_true((T)) \ ) #define JNI_jchar_to_term(J,T) \ PL_unify_integer((T),(int)(J)) #define JNI_jbyte_to_term(J,T) \ PL_unify_integer((T),(int)(J)) #define JNI_jshort_to_term(J,T) \ PL_unify_integer((T),(int)(J)) #define JNI_jint_to_term(J,T) \ PL_unify_integer((T),(int)(J)) #define JNI_jlong_to_term(J,T) \ ( ( jl=(J), \ xhi=((int*)&jl)[1], \ xlo=((int*)&jl)[0], \ TRUE \ ) \ && ( ( xhi== 0 && xlo>=0 ) \ || ( xhi==-1 && xlo< 0 ) \ ) \ ? PL_unify_integer((T),xlo) \ : PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_jlong_2, \ PL_INTEGER, xhi, \ PL_INTEGER, xlo \ ) \ ) #define JNI_jfloat_to_term(J,T) \ PL_unify_float((T),(double)(J)) #define JNI_jdouble_to_term(J,T) \ PL_unify_float((T),(double)(J)) // J can be an *expression* parameter to this macro; // we must evaluate it exactly once; hence we save its value // in the variable j, which must be dynamic (e.g. local) // if this macro is to be re-entrant #define JNI_jobject_to_term(J,T) \ ( ( j=(J), j==NULL ) \ ? PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_at_1, \ PL_ATOM, JNI_atom_null \ ) \ : ( (*env)->IsInstanceOf(env,j,str_class) \ ? jni_string_to_atom(j,&a) \ && PL_unify_term((T), \ PL_ATOM, a \ ) \ : jni_object_to_iref(j,&i) \ && jni_iref_to_tag(i,&a) \ && PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_at_1, \ PL_ATOM, a \ ) \ ) \ ) #define JNI_jfieldID_to_term(J,T) \ PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_jfieldID_1, \ PL_POINTER, (void*)(J) \ ) #define JNI_jmethodID_to_term(J,T) \ PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_jmethodID_1, \ PL_POINTER, (void*)(J) \ ) #define JNI_jbuf_to_term(J,T,TP) \ PL_unify_term((T), \ PL_FUNCTOR, JNI_functor_jbuf_2, \ PL_POINTER, (void*)(J), \ PL_ATOM, (TP) \ ) #define JNI_pointer_to_term(J,T) \ PL_unify_pointer((T),(void*)(J)) #define JNI_charP_to_term(J,T) \ PL_unify_atom_chars((T),(J)) //=== JNI initialisation macro (typically succeeds cheaply) ======================================== #define jni_ensure_jvm() ( ( jvm != NULL \ || jni_create_default_jvm() \ ) \ && jni_get_env() \ ) //=== JPL initialisation macros (typically succeed cheaply) ======================================== // outcomes: // fail to find jpl.*, jpl.fli.* classes or to convert init args to String[]: exception, FALSE // JPL is (newly or already) out of RAW state: TRUE #define jpl_ensure_jpl_init(e) ( jpl_status != JPL_INIT_RAW \ || jpl_do_jpl_init(e) \ ) // outcomes: // JPL or PVM init has already failed: FALSE // JPL or PVM init fails while being necessarily attempted: exception // JPL is (newly or already) fully initialised: TRUE #define jpl_ensure_pvm_init(e) ( jpl_status == JPL_INIT_OK \ || ( jpl_ensure_jpl_init(e) , FALSE ) \ || jpl_test_pvm_init(e) \ || jpl_do_pvm_init(e) \ ) //=== types (structs and typedefs) ================================================================= // types for "hashed refs": typedef struct Hr_Entry HrEntry; // enables circular definition... struct Hr_Entry { // a single interned reference jobject obj; // a JNI global ref int hash; // identityHashCode(obj) HrEntry *next; // next entry in this chain, or NULL }; typedef struct Hr_Table HrTable; struct Hr_Table { int count; // current # entries int threshold; // rehash on add when count==threshold int length; // # slots in slot array HrEntry **slots; // pointer to slot array }; typedef long pointer; // for JPL (I reckon 'int' is enough on 32-bit systems) typedef int bool; // for JNI/JPL functions returning only TRUE or FALSE //=== JNI "constants" ============================================================================== // sizes of JNI primitive types: int size[16] = { // NB relies on sequence of JNI_XPUT_* defs 0, sizeof(jboolean), // size[JNI_XPUT_BOOLEAN] sizeof(jbyte), // size[JNI_XPUT_BYTE] sizeof(jchar), // size[JNI_XPUT_CHAR] sizeof(jshort), // size[JNI_XPUT_SHORT] sizeof(jint), // size[JNI_XPUT_INT] sizeof(jlong), // size[JNI_XPUT_LONG] sizeof(jfloat), // size[JNI_XPUT_FLOAT] sizeof(jdouble), // size[JNI_XPUT_DOUBLE] 0, // n/a - JNI_FLOAT_TO_DOUBLE 0, // n/a - JNI_LONG_TO_FLOAT 0, // n/a - JNI_LONG_TO_DOUBLE 0, // n/a - JNI_REF 0, // n/a - JNI_ATOM 0, // n/a - JNI_JVALUEP sizeof(jvalue) // size[JNI_XPUT_JVALUE] }; //=== JNI "constants", lazily initialised by jni_init() ============================================ static atom_t JNI_atom_false; // false static atom_t JNI_atom_true; // true static atom_t JNI_atom_boolean; // boolean static atom_t JNI_atom_char; // char static atom_t JNI_atom_byte; // byte static atom_t JNI_atom_short; // short static atom_t JNI_atom_int; // int static atom_t JNI_atom_long; // long static atom_t JNI_atom_float; // float static atom_t JNI_atom_double; // double static atom_t JNI_atom_null; // null static atom_t JNI_atom_void; // void static functor_t JNI_functor_at_1; // @(_) static functor_t JNI_functor_jbuf_2; // jbuf(_,_) static functor_t JNI_functor_jlong_2; // jlong(_,_) static functor_t JNI_functor_jfieldID_1; // jfieldID(_) static functor_t JNI_functor_jmethodID_1; // jmethodID(_) static functor_t JNI_functor_error_2; // error(_, _) static functor_t JNI_functor_java_exception_1; // java_exception(_) static functor_t JNI_functor_jpl_error_1; // jpl_error(_) //=== JNI's static JVM references, lazily initialised by jni_init() ================================ static jclass c_class; // java.lang.Class (rename to jClass_c ?) static jmethodID c_getName; // java.lang.Class' getName() (rename to jClassGetName_m ?) static jclass str_class; // java.lang.String (this duplicates jString_c below) static jclass sys_class; // java.lang.System (rename to jSystem_c ?) static jmethodID sys_ihc; // java.lang.System's identityHashCode() (rename to jSystemIdentityHashCode_m ?) //=== JPL's reusable global class object refs, initialised by jpl_ensure_jpl_init() ================ static jclass jString_c; static jclass jJPLException_c; static jclass jTermT_c; static jclass jAtomT_c; static jclass jFunctorT_c; static jclass jFidT_c; static jclass jPredicateT_c; static jclass jQidT_c; static jclass jModuleT_c; static jclass jEngineT_c; static jclass jLongHolder_c; static jclass jPointerHolder_c; static jclass jIntHolder_c; static jclass jDoubleHolder_c; static jclass jStringHolder_c; static jclass jObjectHolder_c; static jclass jBooleanHolder_c; static jclass jJRef_c; static jclass jJBoolean_c; //=== JPL's reusable constant field IDs, set before first use by jpl_ensure_jpl_init() ============= static jfieldID jLongHolderValue_f; static jfieldID jPointerHolderValue_f; static jfieldID jIntHolderValue_f; static jfieldID jDoubleHolderValue_f; static jfieldID jStringHolderValue_f; static jfieldID jObjectHolderValue_f; static jfieldID jBooleanHolderValue_f; static jfieldID jJRefRef_f; static jfieldID jJBooleanValue_f; //=== JPL's default args for PL_initialise() (NB these are not really good enough) ================= const char *default_args[] = { "pl", "-g", "true", NULL }; // *must* have final NULL //=== JNI global state (initialised by jni_create_jvm_c) =========================================== static JavaVM *jvm = NULL; // non-null -> JVM successfully loaded & initialised static JNIEnv *env; // if jvm is defined, then so will this be //=== JNI global state (hashed global refs) ======================================================== static HrTable *hr_table = NULL; // static handle to allocated-on-demand table static int hr_add_count = 0; // cumulative total of new refs interned static int hr_old_count = 0; // cumulative total of old refs reused static int hr_del_count = 0; // cumulative total of dead refs released //=== JPL global state, initialised by jpl_ensure_jpl_init() or jpl_ensure_jvm_init() ============== static int jpl_status = JPL_INIT_RAW; // neither JPL nor PVM initialisation has occurred static jobject dia = NULL; // default init args (after jpl init, until pvm init) static jobject aia = NULL; // actual init args (after pvm init) static PL_engine_t *engines = NULL; // handles of the pooled Prolog engines static int engines_allocated = 0; /* size of engines array */ static pthread_mutex_t engines_mutex = PTHREAD_MUTEX_INITIALIZER; // for controlling pool access static pthread_cond_t engines_cond = PTHREAD_COND_INITIALIZER; // for controlling pool access //=== common functions ============================================================================= static char * jpl_c_lib_version(void) { static char v[100]; // version string static char *vp = NULL; // set to v at first call if ( vp != NULL ) // already set? { return vp; } sprintf( v, "%d.%d.%d-%s", JPL_C_LIB_VERSION_MAJOR, JPL_C_LIB_VERSION_MINOR, JPL_C_LIB_VERSION_PATCH, JPL_C_LIB_VERSION_STATUS); vp = v; return vp; } /* %T jpl_c_lib_version( -atom) */ // ... // static foreign_t jpl_c_java_home( term_t ta ) { return PL_unify_atom_chars(ta,JAVA_HOME); } // ... // static foreign_t jpl_c_lib_version_1_plc( term_t ta ) { return PL_unify_atom_chars(ta,jpl_c_lib_version()); } /* %T jpl_c_lib_version( -integer, -integer, -integer, -atom) */ // ... // static foreign_t jpl_c_lib_version_4_plc( term_t tmajor, term_t tminor, term_t tpatch, term_t tstatus ) { return PL_unify_integer(tmajor,JPL_C_LIB_VERSION_MAJOR) && PL_unify_integer(tminor,JPL_C_LIB_VERSION_MINOR) && PL_unify_integer(tpatch,JPL_C_LIB_VERSION_PATCH) && PL_unify_atom_chars(tstatus,JPL_C_LIB_VERSION_STATUS); } //=== JNI function prototypes (to resolve unavoidable forward references) ========================== static int jni_hr_add(jobject,int*); static int jni_hr_del(int); //=== JNI functions (NB first 6 are cited in macros used subsequently) ============================= // this now checks that the atom's name resembles a tag (PS 18/Jun/2004) static bool jni_tag_to_iref( atom_t a, int *iref ) { const char *s = PL_atom_chars(a); return strlen(s) == 12 && s[0] == 'J' && s[1] == '#' && isdigit(s[2]) && isdigit(s[3]) && isdigit(s[4]) && isdigit(s[5]) && isdigit(s[6]) && isdigit(s[7]) && isdigit(s[8]) && isdigit(s[9]) && isdigit(s[10]) && isdigit(s[11]) // s is like 'J#0123456789' && (*iref=atoi(&s[2])) != 0; } static bool jni_iref_to_tag( int iref, atom_t *a ) { char abuf[13]; sprintf( abuf, "J#%010u", iref); // oughta encapsulate this mapping... *a = PL_new_atom(abuf); PL_unregister_atom(*a); // empirically decrement reference count... return TRUE; // can't fail (?!) } static bool jni_object_to_iref( jobject obj, // a newly returned JNI local ref int *iref // gets an integerised, canonical, global equivalent ) { int r; // temp for result code if ( (r=jni_hr_add(obj,iref)) == JNI_HR_ADD_NEW ) { hr_add_count++; // obj was novel, has been added to dict return TRUE; } else if ( r == JNI_HR_ADD_OLD ) { hr_old_count++; // obj was already in dict return TRUE; } else { return FALSE; // r == JNI_HR_ADD_FAIL, presumably } } // retract all jpl_iref_type_cache(Iref,_) facts static bool jni_tidy_iref_type_cache( int iref ) { term_t goal = PL_new_term_ref(); PL_unify_term( goal, PL_FUNCTOR, PL_new_functor(PL_new_atom("jpl_tidy_iref_type_cache"),1), PL_INTEGER, iref ); return PL_call( goal, PL_new_module(PL_new_atom("user")) ); } // could merge this into jni_hr_del() ? static bool jni_free_iref( // called indirectly from agc hook when a possible iref is unreachable int iref ) { if ( jni_hr_del(iref) ) // iref matched a hashedref table entry? (in which case, was deleted) { if ( !jni_tidy_iref_type_cache(iref) ) { DEBUG(0, Sdprintf( "[JPL: jni_tidy_iref_type_cache(%u) failed]\n", iref)); } hr_del_count++; return TRUE; } else { return FALSE; } } static bool jni_string_to_atom( // called from the JNI_jobject_to_term(J,T) macro jobject obj, atom_t *a ) { const char *cp; return (cp=(*env)->GetStringUTFChars(env,obj,NULL)) != NULL && ( *a=PL_new_atom(cp), TRUE) && ( (*env)->ReleaseStringUTFChars(env,obj,cp), TRUE); } /* %T jni_tag_to_iref( +atom, -integer) */ // an FLI wrapper for jni_tag_to_iref() above // with luck, this will be redundant when hybrid atom+int tag scheme is sorted // is currently called by jpl_tag_to_type/2, jpl_cache_type_of_object/2 // jpl_tag_to_type/2 is called by jpl_object_to_type/2, jpl_ref_to_type/2 // static foreign_t jni_tag_to_iref_plc( term_t tt, term_t ti ) { atom_t a; int iref; return PL_get_atom(tt,&a) && jni_tag_to_iref(a,&iref) && PL_unify_integer(ti,iref); } // this will be hooked to SWI-Prolog's PL_agc_hook, // and is called just before each redundant atom is expunged from the dict // NB need to be able to switch this on and off from Prolog... // static bool jni_atom_freed( atom_t a ) { const char *cp = PL_atom_chars(a); int iref; char cs[11]; if ( jni_tag_to_iref( a, &iref) ) // check format and convert digits to int if ok { sprintf( cs, "%010u", iref); // reconstruct digits part of tag in cs if ( strcmp(&cp[2],cs) != 0 ) // original digits != reconstructed digits? { DEBUG(0, Sdprintf( "[JPL: garbage-collected tag '%s'=%u is bogus (not canonical)]\n", cp, iref)); } else if ( !jni_free_iref(iref) ) // free it (iff it's in the hashedref table) { DEBUG(0, Sdprintf( "[JPL: garbage-collected tag '%s' is bogus (not in HashedRefs)]\n", cp)); } } else { } return TRUE; // means "go ahead and expunge the atom" (we do this regardless) } //=== "hashed ref" (canonical JNI global reference) support ======================================== /* %T jni_hr_info( -term, -term, -term, -term) */ static foreign_t jni_hr_info_plc( // implements jni_hr_info/4 term_t t1, // -integer: # object references currently in hash table term_t t2, // -integer: total # object references so far added term_t t3, // -integer: total # object references so far found to be already in table term_t t4 // -integer: total # object references deleted from table (by atom GC) ) { return PL_unify_integer(t1,(hr_table==NULL?0:hr_table->count)) // 0 was -1 (??) && PL_unify_integer(t2,hr_add_count) && PL_unify_integer(t3,hr_old_count) && PL_unify_integer(t4,hr_del_count); } // unifies t2 with a Prolog term which represents the contents of the hashtable slot // static bool jni_hr_table_slot( term_t t2, HrEntry *slot ) { term_t tp = PL_new_term_ref(); if ( slot == NULL ) { return PL_unify_nil(t2); } else { return PL_unify_list(t2,tp,t2) && PL_unify_term(tp, PL_FUNCTOR, PL_new_functor(PL_new_atom("-"),2), PL_INTEGER, slot->hash, PL_INTEGER, (int)(slot->obj) ) && jni_hr_table_slot(t2,slot->next) ; } } /* %T jni_hr_table( -term) */ // unifies t with a list of hash table slot representations // static foreign_t jni_hr_table_plc( term_t t ) { term_t t1 = PL_copy_term_ref(t); term_t t2 = PL_new_term_ref(); int i; for ( i=0 ; ilength ; i++ ) { if ( !PL_unify_list(t1,t2,t1) || !jni_hr_table_slot(t2,hr_table->slots[i]) ) { return FALSE; } } return PL_unify_nil(t1); } // an empty table of length is successfully created, where none was before // static bool jni_hr_create( int length // required # slots in table ) { int i; // temp for iterative slot initialisation if ( hr_table != NULL ) { return FALSE; // table already exists (destroy before recreating) } if ( length <= 0 ) { return FALSE; // unsuitable length } if ( (hr_table=(HrTable*)malloc(sizeof(HrTable))) == NULL ) { return FALSE; // malloc failed (out of memory, presumably) } hr_table->length = length; hr_table->threshold = (int)(hr_table->length*JNI_HR_LOAD_FACTOR); if ( (hr_table->slots=(HrEntry**)malloc(length*sizeof(HrEntry*))) == NULL ) { return FALSE; // malloc failed: out of memory, presumably } for ( i=0 ; ilength ; i++ ) { hr_table->slots[i] = NULL; } hr_table->count = 0; return TRUE; } // an empty table of some default length is successfully created, where none was before // static bool jni_hr_create_default(void) { return jni_hr_create( 101); } // ep must point to a chain of zero or more entries; they are freed // static void jni_hr_free_chain_entries( HrEntry *ep ) { if ( ep != NULL ) { jni_hr_free_chain_entries( ep->next); free( ep); } } // table t is emptied // static void jni_hr_free_table_chains( HrTable *t ) { int index; for ( index=0 ; index<(t->length) ; index++ ) { jni_hr_free_chain_entries( t->slots[index]); t->slots[index] = NULL; } t->count = 0; } // all dynamic space used by the pointed-to table is freed // static bool jni_hr_free_table( HrTable *t ) { if ( t == NULL ) { return FALSE; // table does not exist } else { jni_hr_free_table_chains( t); free( t); return TRUE; } } // the current table is replaced by an equivalent one with more free space // static bool jni_hr_rehash(void) { HrTable *t0; // old table while building new one from it int i; // for iterating through slots in old table HrEntry *ep1; // for iterating through all entries in old table HrEntry *ep2; // an old table entry being relinked into new table int index; // slot index in new table of entry being transferred t0 = hr_table; // temporarily hold onto former table hr_table = NULL; // precondition for jni_hr_create if ( !jni_hr_create(2*t0->length+1) ) // new bigger table in its place { hr_table = t0; // replace former table for tidiness return FALSE; // failed to create replacement table during rehash } for ( i=0 ; ilength ; i++ ) // for each slot in *former* table { for ( ep1=t0->slots[i] ; ep1!=NULL ; ) { // for each entry in that slot's chain ep2 = ep1; // grab this entry ep1 = ep1->next; // advance to next entry or NULL index = (ep2->hash & 0x7fffffff) % hr_table->length; // new ep2->next = hr_table->slots[index]; // relink into new array hr_table->slots[index] = ep2; // " } t0->slots[i] = NULL; // tidy old array for generic freeing later } hr_table->count = t0->count; // new table's count is old table's count jni_hr_free_table( t0); // free all space used by old table (NB no entries) return TRUE; } static bool jni_hr_hash( jobject obj, // MUST BE a valid non-null reference to a Java object int *hash // gets obj's System.identityHashCode() ) { jobject e; // for possible (but unlikely?) exception *hash = (*env)->CallStaticIntMethod(env,sys_class,sys_ihc,obj,(int)obj); return (e=(*env)->ExceptionOccurred(env))==NULL; } // returns // JNI_HR_ADD_NEW -> referenced object is novel // JNI_HR_ADD_OLD -> referenced object is already known // JNI_HR_ADD_FAIL -> something went wrong // and, in *iref, an integerised canonical global ref to the object // static int jni_hr_add( jobject lref, // new JNI local ref from a regular JNI call int *iref // for integerised canonical global ref ) { int hash; // System.identityHashCode of lref int index; // lref's slot index, from hash HrEntry *ep; // temp entry pointer for chain traversal jobject gref; // iff lref is novel, will hold a global surrogate if ( hr_table==NULL && !jni_hr_create_default() ) { return JNI_HR_ADD_FAIL; // lazy table creation failed: oughta sort return codes } if ( !jni_hr_hash(lref,&hash) ) { return JNI_HR_ADD_FAIL; // System.identityHashCode() failed (?) } index = (hash & 0x7fffffff) % hr_table->length; // make this a macro? for ( ep=hr_table->slots[index] ; ep!=NULL ; ep=ep->next ) { if ( ep->hash==hash ) { if ( (*env)->IsSameObject(env,ep->obj,lref) ) { // newly referenced object is already interned (*env)->DeleteLocalRef(env,lref); // free redundant new ref *iref = (int)(ep->obj); // old, equivalent (global) ref return JNI_HR_ADD_OLD; } } } if ( hr_table->count >= hr_table->threshold ) { (void)jni_hr_rehash(); // oughta check for failure, and return it... return jni_hr_add(lref,iref); // try again with new, larger table } // referenced object is novel, and we can add it to table if ( (gref=(*env)->NewGlobalRef(env,lref)) == NULL ) // derive a global ref { return JNI_HR_ADD_FAIL; } (*env)->DeleteLocalRef(env,lref); // free redundant (local) ref ep = (HrEntry*)malloc(sizeof(HrEntry)); ep->hash = hash; ep->obj = gref; ep->next = hr_table->slots[index]; // insert at front of chain hr_table->slots[index] = ep; hr_table->count++; *iref = (int)gref; // pass back the (new) global ref return JNI_HR_ADD_NEW; // obj was newly interned, under iref as supplied } // iref corresponded to an entry in the current HashedRef table; // now that entry is gone, its space is recovered, counts are adjusted etc. // static bool jni_hr_del( int iref // a possibly spurious canonical global iref ) { int index; // index to a HashedRef table slot HrEntry *ep; // pointer to a HashedRef table entry HrEntry **epp; // pointer to ep's handle, in case it needs updating DEBUG(1, Sdprintf( "[removing possible object reference %u]\n", obj)); for ( index=0 ; indexlength ; index++ ) // for each slot { for ( epp=&(hr_table->slots[index]), ep=*epp ; ep!=NULL ; epp=&(ep->next), ep=*epp ) { if ( (int)(ep->obj) == iref ) // found the sought entry? { (*env)->DeleteGlobalRef( env, ep->obj); // free the global object reference *epp = ep->next; // bypass the entry free( ep); // free the now-redundant space hr_table->count--; // adjust table's entry count DEBUG(1, Sdprintf( "[found & removed hashtable entry for object reference %u]\n", iref)); // should we do something with jni_iref_tidy_type_cache() here? return TRUE; // entry found and removed } } } DEBUG(1, Sdprintf("[JPL: failed to find hashtable entry for (presumably bogus) object reference %u]\n", iref)); return FALSE; } #if 0 /* These functions are not yet used */ static void jni_hr_destroy() // tidily returns to consistent "table absent" state { jni_hr_free_table( hr_table); hr_table = NULL; } // this gets called OK, but I don't know the state of the JVM, // or what happens to a pending JNI call // static void jvm_exit( jint code ) { // term_t e = PL_new_term_ref(); // PL_unify_term( e, // PL_FUNCTOR, JNI_functor_java_exception_2, // PL_CHARS, "exited", // PL_INTEGER, code // ); // return PL_raise_exception(e); DEBUG(0, Sdprintf( "[JPL: JVM exits: code=%d]\n", code)); } // this gets called OK, but I don't know the state of the JVM, // or what happens to a pending JNI call // static void jvm_abort(void) { // term_t e = PL_new_term_ref(); // PL_unify_term( e, // PL_FUNCTOR, JNI_functor_java_exception_2, // PL_CHARS, "aborted", // PL_INTEGER, 0 // ); // return PL_raise_exception(e); DEBUG(0, Sdprintf( "[JPL: JVM aborts]\n")); } #endif /*0*/ // called once: after successful PVM & JVM creation/discovery, before any JNI calls // static int jni_init(void) { jclass lref; // temporary local ref, replaced by global // these initialisations require an active PVM: JNI_atom_false = PL_new_atom( "false"); JNI_atom_true = PL_new_atom( "true"); JNI_atom_boolean = PL_new_atom( "boolean"); JNI_atom_char = PL_new_atom( "char"); JNI_atom_byte = PL_new_atom( "byte"); JNI_atom_short = PL_new_atom( "short"); JNI_atom_int = PL_new_atom( "int"); JNI_atom_long = PL_new_atom( "long"); JNI_atom_float = PL_new_atom( "float"); JNI_atom_double = PL_new_atom( "double"); JNI_atom_null = PL_new_atom( "null"); JNI_atom_void = PL_new_atom( "void"); // not yet used properly (?) JNI_functor_at_1 = PL_new_functor( PL_new_atom("@"), 1); JNI_functor_jbuf_2 = PL_new_functor( PL_new_atom("jbuf"), 2); JNI_functor_jlong_2 = PL_new_functor( PL_new_atom("jlong"), 2); JNI_functor_jfieldID_1 = PL_new_functor( PL_new_atom("jfieldID"), 1); JNI_functor_jmethodID_1 = PL_new_functor( PL_new_atom("jmethodID"), 1); JNI_functor_error_2 = PL_new_functor(PL_new_atom("error"), 2); JNI_functor_java_exception_1 = PL_new_functor( PL_new_atom("java_exception"), 1); JNI_functor_jpl_error_1 = PL_new_functor( PL_new_atom("jpl_error"), 1); (void)PL_agc_hook( jni_atom_freed); // link atom GC to object GC (cool:-) // these initialisations require an active JVM: return ( (lref=(*env)->FindClass(env,"java/lang/Class")) != NULL && (c_class=(*env)->NewGlobalRef(env,lref)) != NULL && ( (*env)->DeleteLocalRef(env,lref), TRUE) && (lref=(*env)->FindClass(env,"java/lang/String")) != NULL && (str_class=(*env)->NewGlobalRef(env,lref)) != NULL && ( (*env)->DeleteLocalRef(env,lref), TRUE) && (c_getName=(*env)->GetMethodID(env,c_class,"getName","()Ljava/lang/String;")) != NULL && (lref=(*env)->FindClass(env,"java/lang/System")) != NULL && (sys_class=(*env)->NewGlobalRef(env,lref)) != NULL && ( (*env)->DeleteLocalRef(env,lref), TRUE) && (sys_ihc=(*env)->GetStaticMethodID(env,sys_class,"identityHashCode","(Ljava/lang/Object;)I")) != NULL ? 0 : -7 // NB #define this? ) ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jni_new_java_exception(char *comment, atom_t ex) Throw a java exception as error(java_exception(@ex), comment) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static term_t jni_new_java_exception( // construct a Prolog exception structure java_exception/2 const char *m, // to represent a caught Java exception atom_t a ) { term_t e = PL_new_term_ref(); PL_unify_term(e, PL_FUNCTOR, JNI_functor_error_2, PL_FUNCTOR, JNI_functor_java_exception_1, PL_FUNCTOR, JNI_functor_at_1, PL_ATOM, a, PL_CHARS, m); return e; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jni_new_jpl_error(char *comment, atom_t ex) As above, but used for internal JPL errors - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static term_t jni_new_jpl_error( // construct a Prolog exception structure jpl_error/2 const char *m, // to represent an exceptional condition within JSP atom_t a ) { term_t e = PL_new_term_ref(); PL_unify_term(e, PL_FUNCTOR, JNI_functor_error_2, PL_FUNCTOR, JNI_functor_jpl_error_1, PL_FUNCTOR, JNI_functor_at_1, PL_ATOM, a, PL_CHARS, m); return e; } // test for a raised exception; clear and report it if found // static bool jni_check_exception(void) { jobject ej; // the pending Java exception, if any jobject c; // its class jobject s; // its class name as a JVM String, for the report const char *cp; // its class name as a C string term_t ep; // a newly created Prolog exception int i; // temp for an iref denoting a Java exception atom_t a; // temp for a tag denoting a Java exception if ( (ej=(*env)->ExceptionOccurred(env)) == NULL ) { return TRUE; } else { (*env)->ExceptionClear(env); // clear "exception-pending" state so we can do JNI calls if ( (c=(*env)->GetObjectClass(env,ej)) != NULL ) { // we've got its class if ( (s=(*env)->CallObjectMethod(env,c,c_getName)) != NULL ) { // we've got its name as a String if ( jni_object_to_iref(ej,&i) ) { if ( jni_iref_to_tag(i,&a) ) { if ( (cp=(*env)->GetStringUTFChars(env,s,NULL)) != NULL ) { DEBUG(1, Sdprintf( "[#JNI exception occurred: %s]\n", cp)); ep = jni_new_java_exception(cp,a); (*env)->ReleaseStringUTFChars(env,s,cp); } else { ep = jni_new_jpl_error("FailedToGetUTFCharsOfNameOfClassOfException",a); } } else { ep = jni_new_jpl_error("FailedToConvertExceptionIrefToTagatom",JNI_atom_null); } } else { ep = jni_new_jpl_error("FailedToConvertExceptionObjectToIref",JNI_atom_null); } (*env)->DeleteLocalRef(env,s); } else { ep = jni_new_jpl_error("FailedToGetNameOfClassOfException",JNI_atom_null); } (*env)->DeleteLocalRef(env,c); } else { ep = jni_new_jpl_error("FailedToGetClassOfException",JNI_atom_null); } return PL_raise_exception(ep); } } //=== buffer and method param transput ============================================================= /* %T jni_byte_buf_length_to_codes( +integer, +integer, -term) */ static foreign_t jni_byte_buf_length_to_codes_plc( // carefully s/chars/codes/ :-( term_t tbb, term_t tlen, term_t tcs ) { functor_t fn; term_t a1; atom_t a; term_t a2; jbyte *bb; int len; int i; term_t tl = PL_copy_term_ref( tcs); term_t ta = PL_new_term_ref(); void *ptr; if ( !( PL_get_functor(tbb,&fn) && fn==JNI_functor_jbuf_2 && ( a2=PL_new_term_ref(), PL_get_arg(2,tbb,a2) ) && PL_get_atom(a2,&a) && a==JNI_atom_byte && ( a1=PL_new_term_ref(), PL_get_arg(1,tbb,a1) ) && PL_get_pointer(a1,&ptr) ) || !PL_get_integer(tlen,&len) ) { return FALSE; } bb = ptr; for ( i=0 ; i first) term_t txc, // transput code, as Prolog integer, appropriate to this param term_t tt, // param value as datum (value or ref) term_t tjvp // param buffer (allocated just for this call) ) { int n; // got from tn (see above) int xc; // got from txc (see above) jvalue *jvp; // got from tjvp (see above) functor_t fn; // temp for conversion macros term_t a1; // " term_t a2; // " atom_t a; // " char *cp; // " int i; // " int xhi; // " int xlo; // " // jobject j; // " jlong jl; // " int ix; // temp for conversion double dx; // " long lx; // " void *ptr; if ( !PL_get_integer(tn,&n) || !PL_get_integer(txc,&xc) || !PL_get_pointer(tjvp,&ptr) ) { return FALSE; } jvp = ptr; switch ( xc ) { case JNI_XPUT_BOOLEAN: return JNI_term_to_jboolean(tt,jvp[n].z); case JNI_XPUT_BYTE: return PL_get_integer(tt,&ix) && ix >= JNI_MIN_JBYTE && ix <= JNI_MAX_JBYTE && ( (jvp[n].b=(jboolean)ix) , TRUE ); case JNI_XPUT_CHAR: return PL_get_integer(tt,&ix) && ix >= JNI_MIN_JCHAR && ix <= JNI_MAX_JCHAR && ( (jvp[n].c=(jchar)ix) , TRUE ); case JNI_XPUT_SHORT: return PL_get_integer(tt,&ix) && ix >= JNI_MIN_JSHORT && ix <= JNI_MAX_JSHORT && ( (jvp[n].s=(jshort)ix) , TRUE ); case JNI_XPUT_INT: return JNI_term_to_jint(tt,jvp[n].i); case JNI_XPUT_LONG: return JNI_term_to_jlong(tt,jvp[n].j); case JNI_XPUT_FLOAT: return ( PL_get_float(tt,&dx) ? ( jvp[n].f=(jfloat)dx, TRUE) : ( PL_get_integer(tt,&ix) ? ( jvp[n].f=(jfloat)ix, TRUE) : ( JNI_jlong2_to_jlong(tt,lx) ? ( jvp[n].f=(jfloat)lx, TRUE) : FALSE ) ) ); case JNI_XPUT_DOUBLE: return JNI_term_to_jdouble(tt,jvp[n].d); case JNI_XPUT_REF: return JNI_term_to_ref(tt,jvp[n].l); default: return FALSE; // unknown or inappropriate JNI_XPUT_* code } } /* %T jni_alloc_buffer( +integer, +integer, -integer) */ // for completeness, allocates zero-length buffers too, // while avoiding malloc() problems // static foreign_t jni_alloc_buffer_plc( term_t txc, // +transput code term_t tlen, // +required length (# items) term_t tbp // -PL_POINTER to newly allocated buffer ) { int xc; int len; void *bp; return PL_get_integer(txc,&xc) && ( ( xc>=JNI_XPUT_BOOLEAN && xc<=JNI_XPUT_DOUBLE ) || xc==JNI_XPUT_JVALUE ) && PL_get_integer(tlen,&len) && len >= 0 && (bp=malloc((len==0?1:len)*size[xc])) != NULL // avoid (unsafe) malloc(0) && ( PL_unify_pointer(tbp,(void*)bp) ? TRUE : ( free(bp), FALSE) ) ; } /* %T jni_free_buffer( +integer) */ static foreign_t jni_free_buffer_plc( term_t tbp // +pointer: a redundant buffer ) { void *bp; return PL_get_pointer(tbp,&bp) && ( free(bp), TRUE); } /* %T jni_fetch_buffer_value( +integer, +integer, +integer, -integer, -term) */ // NB simplify this routine as done for jni_params_put // static foreign_t jni_fetch_buffer_value_plc( term_t tbp, // +pointer: an active buffer from jni_alloc_buffer/3 term_t ti, // +integer: index into buffer; 0 <= i < length term_t tv2, // -integer: hi int of value, or 0 term_t tv1, // -integer|-float: lo int of value, or float term_t txc // +integer: transput code (one of JNI_XPUT_*) ) { void *bp; // buffer address (trusted to be valid) int i; // buffer index (trusted to be valid) int xc; // transput code (range-checked by switch statement) if ( !PL_get_pointer(tbp,&bp) || !PL_get_integer(ti,&i) || !PL_get_integer(txc,&xc) ) { return FALSE; } switch ( xc ) { case JNI_XPUT_BOOLEAN: return PL_unify_integer(tv2,0) && PL_unify_integer(tv1,((jboolean*)bp)[i]); case JNI_XPUT_CHAR: return PL_unify_integer(tv2,0) && PL_unify_integer(tv1,((jchar*)bp)[i]); case JNI_XPUT_BYTE: return PL_unify_integer(tv2,0) && PL_unify_integer(tv1,((jbyte*)bp)[i]); case JNI_XPUT_SHORT: return PL_unify_integer(tv2,0) && PL_unify_integer(tv1,((jshort*)bp)[i]); case JNI_XPUT_INT: return PL_unify_integer(tv2,0) && PL_unify_integer(tv1,((jint*)bp)[i]); case JNI_XPUT_LONG: return PL_unify_integer(tv2,((int*)&((jlong*)bp)[i])[1]) && PL_unify_integer(tv1,((int*)&((jlong*)bp)[i])[0]); case JNI_XPUT_FLOAT: return PL_unify_integer(tv2,0) && PL_unify_float(tv1,((jfloat*)bp)[i]); case JNI_XPUT_DOUBLE: return PL_unify_integer(tv2,((int*)&((jdouble*)bp)[i])[1]) && PL_unify_integer(tv1,((int*)&((jdouble*)bp)[i])[0]); default: return FALSE; } } /* %T jni_stash_buffer_value( +integer, +integer, +integer, +term, +integer) */ static foreign_t jni_stash_buffer_value_plc( term_t tbp, term_t ti, term_t tv2, term_t tv1, term_t txc ) { void *bp; int i; int xc; // int v1; // int v2; jlong vjl; double vd; if ( !PL_get_pointer(tbp,&bp) || !PL_get_integer(ti,&i) || !PL_get_integer(txc,&xc) ) { return FALSE; } switch ( xc ) { case JNI_XPUT_BOOLEAN: return PL_get_integer(tv1,(int*)&((jboolean*)bp)[i]); // NB not &(int) case JNI_XPUT_CHAR: return PL_get_integer(tv1,(int*)&((jchar*)bp)[i]); // NB not &(int) case JNI_XPUT_BYTE: return PL_get_integer(tv1,(int*)&((jbyte*)bp)[i]); // NB not &(int) case JNI_XPUT_SHORT: return PL_get_integer(tv1,(int*)&((jshort*)bp)[i]); // NB not &(int) case JNI_XPUT_INT: return PL_get_integer(tv1,(int*)&((jint*)bp)[i]); case JNI_XPUT_LONG: return PL_get_integer(tv2,&((int*)&((jlong*)bp)[i])[1]) && PL_get_integer(tv1,&((int*)&((jlong*)bp)[i])[0]); case JNI_XPUT_FLOAT: return PL_get_float(tv1,&vd) && ( ((jfloat*)bp)[i]=(jfloat)vd, TRUE); case JNI_XPUT_DOUBLE: return PL_get_integer(tv2,&((int*)&((jdouble*)bp)[i])[1]) && PL_get_integer(tv2,&((int*)&((jdouble*)bp)[i])[0]); case JNI_XPUT_FLOAT_TO_DOUBLE: return PL_get_float(tv1,&((jdouble*)bp)[i]); case JNI_XPUT_LONG_TO_FLOAT: return PL_get_integer(tv2,&((int*)&vjl)[1]) && PL_get_integer(tv1,&((int*)&vjl)[0]) && ( ((jfloat*)bp)[i]=(jfloat)vjl, TRUE); case JNI_XPUT_LONG_TO_DOUBLE: return PL_get_integer(tv2,&((int*)&vjl)[1]) && PL_get_integer(tv1,&((int*)&vjl)[0]) && ( ((jdouble*)bp)[i]=(jdouble)vjl, TRUE); default: return FALSE; } } //=== JVM initialisation, startup etc. ============================================================= // this isn't much use; it can't discover JDK 1.2 support... static int jni_supported_jvm_version( int major, int minor ) { JDK1_1InitArgs vm_args; int mhi; int mlo; vm_args.version = ((major&0xFFFF)<<16) + (minor&0xFFFF); JNI_GetDefaultJavaVMInitArgs( &vm_args); mhi = (vm_args.version>>16)&0xFFFF; mlo = (vm_args.version)&0xFFFF; DEBUG(1, Sdprintf( "JNI_GetDefaultJavaVMInitArgs() returns %d,%d\n", mhi, mlo)); return major == mhi && minor == mlo ; } static int jni_get_created_jvm_count(void) { int n; return ( JNI_GetCreatedJavaVMs(NULL,0,&n) == 0 // what does the '0' arg mean? ? n : -1 ) ; } // this could be inlined, or made into a macro? static int jni_get_env(void) { JNIEnv *env0 = env; int r; r = (*jvm)->GetEnv(jvm,(void**)&env,JNI_VERSION_1_2) == JNI_OK; if ( env != env0 ) { DEBUG(1, Sdprintf( "[new env=%u]\n", (void*)env)); } return r; } #define MAX_JVM_OPTIONS 10 static int jni_create_jvm_c( char *classpath ) { JavaVMInitArgs vm_args; char cpopt[1000]; JavaVMOption opt[MAX_JVM_OPTIONS]; int r; int n; int optn = 0; DEBUG(1, Sdprintf( "[creating JVM with 'java.class.path=%s']\n", classpath)); vm_args.version = JNI_VERSION_1_2; // "Java 1.2 please" if ( classpath ) { strcpy( cpopt, "-Djava.class.path="); strcat( cpopt, classpath); // oughta check length... vm_args.options = opt; opt[optn].optionString = cpopt; optn++; } // opt[optn++].optionString = "-Djava.compiler=NONE"; // opt[optn].optionString = "exit"; // I don't understand this yet... // opt[optn++].extraInfo = jvm_exit; // opt[optn].optionString = "abort"; // I don't understand this yet... // opt[optn++].extraInfo = jvm_abort; // opt[optn++].optionString = "-Xcheck:jni"; // extra checking of JNI calls // opt[optn++].optionString = "-Xnoclassgc"; // so method/field IDs remain valid (?) // opt[optn].optionString = "vfprintf"; // opt[optn++].extraInfo = fprintf; // no O/P, then SEGV // opt[optn++].extraInfo = xprintf; // one message, then SEGV // opt[optn++].optionString = "-verbose:jni"; vm_args.nOptions = optn; // vm_args.ignoreUnrecognized = TRUE; return ( JNI_GetCreatedJavaVMs(&jvm,1,&n) == 0 // what does the '1' arg mean? && n == 1 // && (r=(*jvm)->GetEnv(jvm,(void**)&env,JNI_VERSION_1_2)) == JNI_OK && jni_get_env() ? 2 // success (JVM already available) : ( (r=JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args)) == 0 ? 0 // success (JVM created OK) : ( jvm=NULL, r) // -ve, i.e. some create error ) ); } static foreign_t jni_supported_jvm_version_plc( // not as useful as I'd hoped... term_t t1, term_t t2 ) { int major; int minor; return PL_get_integer(t1,&major) && PL_get_integer(t2,&minor) && jni_supported_jvm_version(major,minor) ; } static foreign_t jni_get_created_jvm_count_plc( term_t t1 ) { return PL_unify_integer(t1,jni_get_created_jvm_count()); } static int jni_create_jvm( char *cp ) { int r1; int r2; DEBUG(1, Sdprintf("[JPL: checking for Java VM...]\n")); return ( jvm != NULL ? 1 // already initialised : ( (r1=jni_create_jvm_c(cp)) < 0 ? r1 // err code from JVM-specific routine : ( (r2=jni_init()) < 0 ? r2 // err code from jni_init() : ( r1 == 0 // success code from JVM-specific routine ? ( DEBUG(0, Sdprintf("[JPL: Java VM created]\n")), r1) : ( DEBUG(0, Sdprintf("[JPL: Java VM found]\n")), r1) ) ) ) ); } /* %T jni_create_jvm( +string, -integer) */ // is this useful? dangerous? redundant? // static foreign_t jni_create_jvm_plc( // maps jni_create_jvm() into Prolog term_t a1, term_t a2 ) { char *classpath; return PL_get_atom_chars( a1, &classpath) && PL_unify_integer(a2,jni_create_jvm(classpath)); } int jni_create_default_jvm(void) { char *cp; cp = getenv("CLASSPATH"); return jni_create_jvm(cp) >= 0; // e.g. 2 -> "JVM already available" } /* %T jni_ensure_jvm */ static foreign_t jni_ensure_jvm_plc(void) { return jni_ensure_jvm(); } // NB after any JNI call which clearly indicates success, // it is unnecessary to check for an exception // (potential for slight economy here...) /* %T jni_void( +integer) */ static foreign_t jni_void_0_plc( // C identifiers distinguished _0_ etc, Prolog name is overloaded term_t tn ) { int n; // JNI function index jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() // ought this either succeed or throw a JPL error? || !PL_get_integer(tn,&n) // ought this either succeed or throw a Prolog type error? ) { return FALSE; } switch ( n ) { case 17: r = ( (*env)->ExceptionClear(env) , TRUE ); // could just return... break; default: return FALSE; // oughta throw exception (design-time error :-) break; } return jni_check_exception() && r; } /* %T jni_void( +integer, +term) */ static foreign_t jni_void_1_plc( term_t tn, // +FuncIndex term_t ta1 // +Arg1 ) { int n; // JNI function index // functor_t fn; // temp for conversion macros // term_t a1; // " // term_t a2; // " // atom_t a; // " // char *cp; // " // int i; // " // int xhi; // " // int xlo; // " // jobject j; // " // jlong jl; // " // void *p1; // temp for converted (JVM) arg char *c1; // " // int i1; // " // jlong l1; // " // double d1; // " jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 18: r = JNI_term_to_charP(ta1,c1) && ( (*env)->FatalError(env,(char*)c1) , TRUE ); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } return jni_check_exception() && r; } /* %T jni_void( +integer, +term, +term) */ static foreign_t jni_void_2_plc( term_t tn, // +FuncIndex term_t ta1, // +Arg1 term_t ta2 // +Arg2 ) { int n; // JNI function index functor_t fn; // temp for conversion macros term_t a1; // " term_t a2; // " atom_t a; // " char *cp; // " // int i; // " // int xhi; // " // int xlo; // " // jobject j; // " // jlong jl; // " void *p1; // temp for converted (JVM) arg void *p2; // " // char *c1; // " char *c2; // " // int i1; // " // int i2; // " // jlong l1; // " // jlong l2; // " // double d1; // " // double d2; // " jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 166: r = JNI_term_to_jstring(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_char) && ( (*env)->ReleaseStringChars(env,(jstring)p1,(jchar*)p2) , TRUE ); break; case 170: r = JNI_term_to_jstring(ta1,p1) && JNI_term_to_jbuf(ta2,c2,JNI_atom_byte) && ( (*env)->ReleaseStringUTFChars(env,(jstring)p1,(char*)c2) , TRUE ); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } return jni_check_exception() && r; } /* %T jni_void( +integer, +term, +term, +term) */ static foreign_t jni_void_3_plc( term_t tn, // +FuncIndex term_t ta1, // +Arg1 term_t ta2, // +Arg2 term_t ta3 // +Arg3 ) { int n; // JNI function index functor_t fn; // temp for conversion macros term_t a1; // " term_t a2; // " atom_t a; // " char *cp; // " int i; // " int xhi; // " int xlo; // " // jobject j; // " jlong jl; // " void *p1; // temp for converted (JVM) arg void *p2; // " void *p3; // " // char *c1; // " // char *c2; // " // char *c3; // " // int i1; // " int i2; // " int i3; // " // jlong l1; // " // jlong l2; // " jlong l3; // " // double d1; // " // double d2; // " double d3; // " jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 63: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && ( (*env)->CallVoidMethodA(env,(jobject)p1,(jmethodID)p2,jvp) , TRUE ); break; case 143: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && ( (*env)->CallStaticVoidMethodA(env,(jclass)p1,(jmethodID)p2,jvp) , TRUE ); break; case 104: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_ref(ta3,p3) && ( (*env)->SetObjectField(env,(jobject)p1,(jfieldID)p2,(jobject)p3) , TRUE ); break; case 105: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jboolean(ta3,i3) && ( (*env)->SetBooleanField(env,(jobject)p1,(jfieldID)p2,(jboolean)i3) , TRUE ); break; case 106: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jbyte(ta3,i3) && ( (*env)->SetByteField(env,(jobject)p1,(jfieldID)p2,(jbyte)i3) , TRUE ); break; case 107: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jchar(ta3,i3) && ( (*env)->SetCharField(env,(jobject)p1,(jfieldID)p2,(jchar)i3) , TRUE ); break; case 108: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jshort(ta3,i3) && ( (*env)->SetShortField(env,(jobject)p1,(jfieldID)p2,(jshort)i3) , TRUE ); break; case 109: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jint(ta3,i3) && ( (*env)->SetIntField(env,(jobject)p1,(jfieldID)p2,(jint)i3) , TRUE ); break; case 110: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jlong(ta3,l3) && ( (*env)->SetLongField(env,(jobject)p1,(jfieldID)p2,(jlong)l3) , TRUE ); break; case 111: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jfloat(ta3,d3) && ( (*env)->SetFloatField(env,(jobject)p1,(jfieldID)p2,(jfloat)d3) , TRUE ); break; case 112: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jdouble(ta3,d3) && ( (*env)->SetDoubleField(env,(jobject)p1,(jfieldID)p2,(jdouble)d3) , TRUE ); break; case 154: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_ref(ta3,p3) && ( (*env)->SetStaticObjectField(env,(jclass)p1,(jfieldID)p2,(jobject)p3) , TRUE ); break; case 155: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jboolean(ta3,i3) && ( (*env)->SetStaticBooleanField(env,(jclass)p1,(jfieldID)p2,(jboolean)i3) , TRUE ); break; case 156: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jbyte(ta3,i3) && ( (*env)->SetStaticByteField(env,(jclass)p1,(jfieldID)p2,(jbyte)i3) , TRUE ); break; case 157: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jchar(ta3,i3) && ( (*env)->SetStaticCharField(env,(jclass)p1,(jfieldID)p2,(jchar)i3) , TRUE ); break; case 158: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jshort(ta3,i3) && ( (*env)->SetStaticShortField(env,(jclass)p1,(jfieldID)p2,(jshort)i3) , TRUE ); break; case 159: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jint(ta3,i3) && ( (*env)->SetStaticIntField(env,(jclass)p1,(jfieldID)p2,(jint)i3) , TRUE ); break; case 160: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jlong(ta3,l3) && ( (*env)->SetStaticLongField(env,(jclass)p1,(jfieldID)p2,(jlong)l3) , TRUE ); break; case 161: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jfloat(ta3,d3) && ( (*env)->SetStaticFloatField(env,(jclass)p1,(jfieldID)p2,(jfloat)d3) , TRUE ); break; case 162: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_term_to_jdouble(ta3,d3) && ( (*env)->SetStaticDoubleField(env,(jclass)p1,(jfieldID)p2,(jdouble)d3) , TRUE ); break; case 174: r = JNI_term_to_object_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_ref(ta3,p3) && ( (*env)->SetObjectArrayElement(env,(jobjectArray)p1,(jsize)i2,(jobject)p3) , TRUE ); break; case 191: r = JNI_term_to_boolean_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_boolean) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseBooleanArrayElements(env,(jbooleanArray)p1,(jboolean*)p2,(jint)i3) , TRUE ); break; case 192: r = JNI_term_to_byte_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_byte) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseByteArrayElements(env,(jbyteArray)p1,(jbyte*)p2,(jint)i3) , TRUE ); break; case 193: r = JNI_term_to_char_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_char) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseCharArrayElements(env,(jcharArray)p1,(jchar*)p2,(jint)i3) , TRUE ); break; case 194: r = JNI_term_to_short_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_short) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseShortArrayElements(env,(jshortArray)p1,(jshort*)p2,(jint)i3) , TRUE ); break; case 195: r = JNI_term_to_int_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_int) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseIntArrayElements(env,(jintArray)p1,(jint*)p2,(jint)i3) , TRUE ); break; case 196: r = JNI_term_to_long_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_long) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseLongArrayElements(env,(jlongArray)p1,(jlong*)p2,(jint)i3) , TRUE ); break; case 197: r = JNI_term_to_float_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_float) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseFloatArrayElements(env,(jfloatArray)p1,(jfloat*)p2,(jint)i3) , TRUE ); break; case 198: r = JNI_term_to_double_jarray(ta1,p1) && JNI_term_to_jbuf(ta2,p2,JNI_atom_double) && JNI_term_to_jint(ta3,i3) && ( (*env)->ReleaseDoubleArrayElements(env,(jdoubleArray)p1,(jdouble*)p2,(jint)i3) , TRUE ); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } if ( jvp != NULL ) { free( jvp); } return jni_check_exception() && r; } /* %T jni_void( +integer, +term, +term, +term, +term) */ static foreign_t jni_void_4_plc( term_t tn, // +FuncIndex term_t ta1, // +Arg1 term_t ta2, // +Arg2 term_t ta3, // +Arg3 term_t ta4 // +Arg4 ) { int n; // JNI function index functor_t fn; // temp for conversion macros term_t a1; // " term_t a2; // " atom_t a; // " char *cp; // " // int i; // " // int xhi; // " // int xlo; // " // jobject j; // " // jlong jl; // " void *p1; // temp for converted (JVM) arg void *p2; // " void *p3; // " void *p4; // " // char *c1; // " // char *c2; // " // char *c3; // " // char *c4; // " // int i1; // " int i2; // " int i3; // " // int i4; // " // jlong l1; // " // jlong l2; // " // jlong l3; // " // jlong l4; // " // double d1; // " // double d2; // " // double d3; // " // double d4; // " jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 93: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jclass(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && ( (*env)->CallNonvirtualVoidMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp) , TRUE ); break; case 199: r = JNI_term_to_boolean_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_boolean) && ( (*env)->GetBooleanArrayRegion(env,(jbooleanArray)p1,(jsize)i2,(jsize)i3,(jboolean*)p4) , TRUE ); break; case 200: r = JNI_term_to_byte_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_byte) && ( (*env)->GetByteArrayRegion(env,(jbyteArray)p1,(jsize)i2,(jsize)i3,(jbyte*)p4) , TRUE ); break; case 201: r = JNI_term_to_char_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_char) && ( (*env)->GetCharArrayRegion(env,(jcharArray)p1,(jsize)i2,(jsize)i3,(jchar*)p4) , TRUE ); break; case 202: r = JNI_term_to_short_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_short) && ( (*env)->GetShortArrayRegion(env,(jshortArray)p1,(jsize)i2,(jsize)i3,(jshort*)p4) , TRUE ); break; case 203: r = JNI_term_to_int_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_int) && ( (*env)->GetIntArrayRegion(env,(jintArray)p1,(jsize)i2,(jsize)i3,(jint*)p4) , TRUE ); break; case 204: r = JNI_term_to_long_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_long) && ( (*env)->GetLongArrayRegion(env,(jlongArray)p1,(jsize)i2,(jsize)i3,(jlong*)p4) , TRUE ); break; case 205: r = JNI_term_to_float_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_float) && ( (*env)->GetFloatArrayRegion(env,(jfloatArray)p1,(jsize)i2,(jsize)i3,(jfloat*)p4) , TRUE ); break; case 206: r = JNI_term_to_double_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_double) && ( (*env)->GetDoubleArrayRegion(env,(jdoubleArray)p1,(jsize)i2,(jsize)i3,(jdouble*)p4) , TRUE ); break; case 207: r = JNI_term_to_boolean_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_boolean) && ( (*env)->SetBooleanArrayRegion(env,(jbooleanArray)p1,(jsize)i2,(jsize)i3,(jboolean*)p4) , TRUE ); break; case 208: r = JNI_term_to_byte_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_byte) && ( (*env)->SetByteArrayRegion(env,(jbyteArray)p1,(jsize)i2,(jsize)i3,(jbyte*)p4) , TRUE ); break; case 209: r = JNI_term_to_char_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_char) && ( (*env)->SetCharArrayRegion(env,(jcharArray)p1,(jsize)i2,(jsize)i3,(jchar*)p4) , TRUE ); break; case 210: r = JNI_term_to_short_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_short) && ( (*env)->SetShortArrayRegion(env,(jshortArray)p1,(jsize)i2,(jsize)i3,(jshort*)p4) , TRUE ); break; case 211: r = JNI_term_to_int_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_int) && ( (*env)->SetIntArrayRegion(env,(jintArray)p1,(jsize)i2,(jsize)i3,(jint*)p4) , TRUE ); break; case 212: r = JNI_term_to_long_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_long) && ( (*env)->SetLongArrayRegion(env,(jlongArray)p1,(jsize)i2,(jsize)i3,(jlong*)p4) , TRUE ); break; case 213: r = JNI_term_to_float_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_float) && ( (*env)->SetFloatArrayRegion(env,(jfloatArray)p1,(jsize)i2,(jsize)i3,(jfloat*)p4) , TRUE ); break; case 214: r = JNI_term_to_double_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_term_to_jint(ta3,i3) && JNI_term_to_jbuf(ta4,p4,JNI_atom_double) && ( (*env)->SetDoubleArrayRegion(env,(jdoubleArray)p1,(jsize)i2,(jsize)i3,(jdouble*)p4) , TRUE ); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } if ( jvp != NULL ) { free( jvp); } return jni_check_exception() && r; } /* %T jni_func( +integer, -term) */ static foreign_t jni_func_0_plc( term_t tn, // +FuncIndex term_t tr // -Result ) { int n; // JNI function index // functor_t fn; // temp for conversion macros // term_t a1; // " // term_t a2; // " atom_t a; // " // char *cp; // " int i; // " // int xhi; // " // int xlo; // " jobject j; // " // jlong jl; // " jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 4: r = JNI_jint_to_term((*env)->GetVersion(env),tr); break; case 15: r = JNI_jobject_to_term((*env)->ExceptionOccurred(env),tr); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } return jni_check_exception() && r; // surely NEITHER of these throws an exception! } /* %T jni_func( +integer, +term, -term) */ static foreign_t jni_func_1_plc( term_t tn, // +FuncIndex term_t ta1, // +Arg1 term_t tr // -Result ) { int n; // JNI function index functor_t fn; // temp for conversion macros term_t a1; // " // term_t a2; // " atom_t a; // " char *cp; // " int i; // " // int xhi; // " // int xlo; // " jobject j; // " // jlong jl; // " void *p1; // temp for converted (JVM) arg char *c1; // " int i1; // " // jlong l1; // " // double d1; // " jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 6: r = JNI_term_to_charP(ta1,c1) && JNI_jobject_to_term((*env)->FindClass(env,(char*)c1),tr); break; case 10: r = JNI_term_to_jclass(ta1,p1) && JNI_jobject_to_term((*env)->GetSuperclass(env,(jclass)p1),tr); break; case 13: r = JNI_term_to_throwable_jobject(ta1,p1) && JNI_jint_to_term((*env)->Throw(env,(jthrowable)p1),tr); break; case 27: r = JNI_term_to_non_array_jclass(ta1,p1) && JNI_jobject_to_term((*env)->AllocObject(env,(jclass)p1),tr); break; case 31: r = JNI_term_to_jobject(ta1,p1) && JNI_jobject_to_term((*env)->GetObjectClass(env,(jobject)p1),tr); break; case 164: r = JNI_term_to_jstring(ta1,p1) && JNI_jint_to_term((*env)->GetStringLength(env,(jstring)p1),tr); break; case 167: r = JNI_term_to_charP(ta1,c1) && JNI_jobject_to_term((*env)->NewStringUTF(env,(char*)c1),tr); break; case 168: r = JNI_term_to_jstring(ta1,p1) && JNI_jint_to_term((*env)->GetStringUTFLength(env,(jstring)p1),tr); break; case 171: r = JNI_term_to_jarray(ta1,p1) && JNI_jint_to_term((*env)->GetArrayLength(env,(jarray)p1),tr); break; case 175: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewBooleanArray(env,(jsize)i1),tr); break; case 176: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewByteArray(env,(jsize)i1),tr); break; case 177: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewCharArray(env,(jsize)i1),tr); break; case 178: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewShortArray(env,(jsize)i1),tr); break; case 179: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewIntArray(env,(jsize)i1),tr); break; case 180: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewLongArray(env,(jsize)i1),tr); break; case 181: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewFloatArray(env,(jsize)i1),tr); break; case 182: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_jobject_to_term((*env)->NewDoubleArray(env,(jsize)i1),tr); break; case 217: r = JNI_term_to_jobject(ta1,p1) && JNI_jint_to_term((*env)->MonitorEnter(env,(jobject)p1),tr); break; case 218: r = JNI_term_to_jobject(ta1,p1) && JNI_jint_to_term((*env)->MonitorExit(env,(jobject)p1),tr); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } return jni_check_exception() && r; } /* %T jni_func( +integer, +term, +term, -term) */ static foreign_t jni_func_2_plc( term_t tn, // +FuncIndex term_t ta1, // +Arg1 term_t ta2, // +Arg2 term_t tr // -Result ) { int n; // JNI function index functor_t fn; // temp for conversion macros term_t a1; // " // term_t a2; // " atom_t a; // " char *cp; // " int i; // " int xhi; // " int xlo; // " jobject j; // " jlong jl; // " void *p1; // temp for converted (JVM) arg void *p2; // " char *c1; // " char *c2; // " // int i1; // " int i2; // " // jlong l1; // " // jlong l2; // " // double d1; // " // double d2; // " jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 11: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jclass(ta2,p2) && JNI_jboolean_to_term((*env)->IsAssignableFrom(env,(jclass)p1,(jclass)p2),tr); break; case 14: r = JNI_term_to_throwable_jclass(ta1,p1) && JNI_term_to_charP(ta2,c2) && JNI_jint_to_term((*env)->ThrowNew(env,(jclass)p1,(char*)c2),tr); break; case 24: r = JNI_term_to_ref(ta1,p1) && JNI_term_to_ref(ta2,p2) && JNI_jboolean_to_term((*env)->IsSameObject(env,(jobject)p1,(jobject)p2),tr); break; case 32: r = JNI_term_to_ref(ta1,p1) && JNI_term_to_jclass(ta2,p2) && JNI_jboolean_to_term((*env)->IsInstanceOf(env,(jobject)p1,(jclass)p2),tr); break; case 95: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jobject_to_term((*env)->GetObjectField(env,(jobject)p1,(jfieldID)p2),tr); break; case 96: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jboolean_to_term((*env)->GetBooleanField(env,(jobject)p1,(jfieldID)p2),tr); break; case 97: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jbyte_to_term((*env)->GetByteField(env,(jobject)p1,(jfieldID)p2),tr); break; case 98: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jchar_to_term((*env)->GetCharField(env,(jobject)p1,(jfieldID)p2),tr); break; case 99: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jshort_to_term((*env)->GetShortField(env,(jobject)p1,(jfieldID)p2),tr); break; case 100: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jint_to_term((*env)->GetIntField(env,(jobject)p1,(jfieldID)p2),tr); break; case 101: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jlong_to_term((*env)->GetLongField(env,(jobject)p1,(jfieldID)p2),tr); break; case 102: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jfloat_to_term((*env)->GetFloatField(env,(jobject)p1,(jfieldID)p2),tr); break; case 103: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jdouble_to_term((*env)->GetDoubleField(env,(jobject)p1,(jfieldID)p2),tr); break; case 145: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jobject_to_term((*env)->GetStaticObjectField(env,(jclass)p1,(jfieldID)p2),tr); break; case 146: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jboolean_to_term((*env)->GetStaticBooleanField(env,(jclass)p1,(jfieldID)p2),tr); break; case 147: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jbyte_to_term((*env)->GetStaticByteField(env,(jclass)p1,(jfieldID)p2),tr); break; case 148: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jchar_to_term((*env)->GetStaticCharField(env,(jclass)p1,(jfieldID)p2),tr); break; case 149: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jshort_to_term((*env)->GetStaticShortField(env,(jclass)p1,(jfieldID)p2),tr); break; case 150: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jint_to_term((*env)->GetStaticIntField(env,(jclass)p1,(jfieldID)p2),tr); break; case 151: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jlong_to_term((*env)->GetStaticLongField(env,(jclass)p1,(jfieldID)p2),tr); break; case 152: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jfloat_to_term((*env)->GetStaticFloatField(env,(jclass)p1,(jfieldID)p2),tr); break; case 153: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jfieldID(ta2,p2) && JNI_jdouble_to_term((*env)->GetStaticDoubleField(env,(jclass)p1,(jfieldID)p2),tr); break; case 163: r = JNI_term_to_charP(ta1,c1) // oughta be _jcharP, i.e. Unicode && JNI_term_to_non_neg_jint(ta2,i2) && JNI_jobject_to_term((*env)->NewString(env,(jchar*)c1,(jsize)i2),tr); break; case 165: r = JNI_term_to_jstring(ta1,p1) && JNI_jbuf_to_term((*env)->GetStringChars(env,(jstring)p1,(jboolean*)&i2),tr,JNI_atom_boolean) && JNI_jboolean_to_term(i2,ta2); break; case 169: r = JNI_term_to_jstring(ta1,p1) && JNI_jbuf_to_term((*env)->GetStringUTFChars(env,(jstring)p1,(jboolean*)&i2),tr,JNI_atom_byte) && JNI_jboolean_to_term(i2,ta2); break; case 173: r = JNI_term_to_object_jarray(ta1,p1) && JNI_term_to_jint(ta2,i2) && JNI_jobject_to_term((*env)->GetObjectArrayElement(env,(jobjectArray)p1,(jsize)i2),tr); break; case 183: r = JNI_term_to_boolean_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetBooleanArrayElements(env,(jbooleanArray)p1,(jboolean*)&i2),tr,JNI_atom_boolean) && JNI_jboolean_to_term(i2,ta2); break; case 184: r = JNI_term_to_byte_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetByteArrayElements(env,(jbyteArray)p1,(jboolean*)&i2),tr,JNI_atom_byte) && JNI_jboolean_to_term(i2,ta2); break; case 185: r = JNI_term_to_char_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetCharArrayElements(env,(jcharArray)p1,(jboolean*)&i2),tr,JNI_atom_char) && JNI_jboolean_to_term(i2,ta2); break; case 186: r = JNI_term_to_short_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetShortArrayElements(env,(jshortArray)p1,(jboolean*)&i2),tr,JNI_atom_short) && JNI_jboolean_to_term(i2,ta2); break; case 187: r = JNI_term_to_int_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetIntArrayElements(env,(jintArray)p1,(jboolean*)&i2),tr,JNI_atom_int) && JNI_jboolean_to_term(i2,ta2); break; case 188: r = JNI_term_to_long_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetLongArrayElements(env,(jlongArray)p1,(jboolean*)&i2),tr,JNI_atom_long) && JNI_jboolean_to_term(i2,ta2); break; case 189: r = JNI_term_to_float_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetFloatArrayElements(env,(jfloatArray)p1,(jboolean*)&i2),tr,JNI_atom_float) && JNI_jboolean_to_term(i2,ta2); break; case 190: r = JNI_term_to_double_jarray(ta1,p1) && JNI_jbuf_to_term((*env)->GetDoubleArrayElements(env,(jdoubleArray)p1,(jboolean*)&i2),tr,JNI_atom_double) && JNI_jboolean_to_term(i2,ta2); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } return jni_check_exception() && r; } /* %T jni_func( +integer, +term, +term, +term, -term) */ static foreign_t jni_func_3_plc( term_t tn, // +FuncIndex term_t ta1, // +Arg1 term_t ta2, // +Arg2 term_t ta3, // +Arg3 term_t tr // -Result ) { int n; // JNI function index functor_t fn; // temp for conversion macros term_t a1; // " // term_t a2; // " atom_t a; // " char *cp; // " int i; // " int xhi; // " int xlo; // " jobject j; // " jlong jl; // " void *p1; // temp for converted (JVM) arg void *p2; // " void *p3; // " // char *c1; // " char *c2; // " char *c3; // " int i1; // " // int i2; // " // int i3; // " // jlong l1; // " // jlong l2; // " // jlong l3; // " // double d1; // " // double d2; // " // double d3; // " jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 30: r = JNI_term_to_non_array_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jobject_to_term((*env)->NewObjectA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 36: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jobject_to_term((*env)->CallObjectMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 39: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jboolean_to_term((*env)->CallBooleanMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 42: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jbyte_to_term((*env)->CallByteMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 45: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jchar_to_term((*env)->CallCharMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 48: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jshort_to_term((*env)->CallShortMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 51: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jint_to_term((*env)->CallIntMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 54: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jlong_to_term((*env)->CallLongMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 57: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jfloat_to_term((*env)->CallFloatMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 60: r = JNI_term_to_jobject(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jdouble_to_term((*env)->CallDoubleMethodA(env,(jobject)p1,(jmethodID)p2,jvp),tr); break; case 116: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jobject_to_term((*env)->CallStaticObjectMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 119: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jboolean_to_term((*env)->CallStaticBooleanMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 122: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jbyte_to_term((*env)->CallStaticByteMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 125: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jchar_to_term((*env)->CallStaticCharMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 128: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jshort_to_term((*env)->CallStaticShortMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 131: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jint_to_term((*env)->CallStaticIntMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 134: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jlong_to_term((*env)->CallStaticLongMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 137: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jfloat_to_term((*env)->CallStaticFloatMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 140: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jmethodID(ta2,p2) && JNI_term_to_pointer(ta3,jvp) && JNI_jdouble_to_term((*env)->CallStaticDoubleMethodA(env,(jclass)p1,(jmethodID)p2,jvp),tr); break; case 33: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_charP(ta2,c2) && JNI_term_to_charP(ta3,c3) && JNI_jmethodID_to_term((*env)->GetMethodID(env,(jclass)p1,(char*)c2,(char*)c3),tr); break; case 94: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_charP(ta2,c2) && JNI_term_to_charP(ta3,c3) && JNI_jfieldID_to_term((*env)->GetFieldID(env,(jclass)p1,(char*)c2,(char*)c3),tr); break; case 113: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_charP(ta2,c2) && JNI_term_to_charP(ta3,c3) && JNI_jmethodID_to_term((*env)->GetStaticMethodID(env,(jclass)p1,(char*)c2,(char*)c3),tr); break; case 144: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_charP(ta2,c2) && JNI_term_to_charP(ta3,c3) && JNI_jfieldID_to_term((*env)->GetStaticFieldID(env,(jclass)p1,(char*)c2,(char*)c3),tr); break; case 172: r = JNI_term_to_non_neg_jint(ta1,i1) && JNI_term_to_jclass(ta2,p2) && JNI_term_to_ref(ta3,p3) && JNI_jobject_to_term((*env)->NewObjectArray(env,(jsize)i1,(jclass)p2,(jobject)p3),tr); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } if ( jvp != NULL ) { free( jvp); } return jni_check_exception() && r; } /* %T jni_func( +integer, +term, +term, +term, +term, -term) */ static foreign_t jni_func_4_plc( term_t tn, // +FuncIndex term_t ta1, // +Arg1 term_t ta2, // +Arg2 term_t ta3, // +Arg3 term_t ta4, // +Arg4 term_t tr // -Result ) { int n; // JNI function index functor_t fn; // temp for conversion macros term_t a1; // " term_t a2; // " atom_t a; // " char *cp; // " int i; // " int xhi; // " int xlo; // " jobject j; // " jlong jl; // " void *p1; // temp for converted (JVM) arg void *p2; // " void *p3; // " // void *p4; // " char *c1; // " // char *c2; // " // char *c3; // " // char *c4; // " // int i1; // " // int i2; // " // int i3; // " int i4; // " // jlong l1; // " // jlong l2; // " // jlong l3; // " // jlong l4; // " // double d1; // " // double d2; // " // double d3; // " // double d4; // " jvalue *jvp = NULL; // if this is given a buffer, it will be freed after the call jboolean r; // Prolog exit/fail outcome if ( !jni_ensure_jvm() || !PL_get_integer(tn,&n) ) { return FALSE; } switch ( n ) { case 66: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jobject_to_term((*env)->CallNonvirtualObjectMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 69: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jboolean_to_term((*env)->CallNonvirtualBooleanMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 72: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jbyte_to_term((*env)->CallNonvirtualByteMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 75: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jchar_to_term((*env)->CallNonvirtualCharMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 78: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jshort_to_term((*env)->CallNonvirtualShortMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 81: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jint_to_term((*env)->CallNonvirtualIntMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 84: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jlong_to_term((*env)->CallNonvirtualLongMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 87: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jfloat_to_term((*env)->CallNonvirtualFloatMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 90: r = JNI_term_to_jclass(ta1,p1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jmethodID(ta3,p3) && JNI_term_to_pointer(ta4,jvp) && JNI_jdouble_to_term((*env)->CallNonvirtualDoubleMethodA(env,(jobject)p1,(jclass)p2,(jmethodID)p3,jvp),tr); break; case 5: r = JNI_term_to_charP(ta1,c1) && JNI_term_to_jobject(ta2,p2) && JNI_term_to_jbuf(ta3,p3,JNI_atom_byte) && JNI_term_to_jint(ta4,i4) && JNI_jobject_to_term((*env)->DefineClass(env,(char*)c1,(jobject)p2,(jbyte*)p3,(jsize)i4),tr); break; default: return FALSE; // oughta throw exception (design-time error :-) break; } if ( jvp != NULL ) { free( jvp); } return jni_check_exception() && r; } // would it be better style to have this at the end of the file? static PL_extension predspecs[] = { { "jni_create_jvm", 2, jni_create_jvm_plc, 0 }, { "jni_supported_jvm_version", 2, jni_supported_jvm_version_plc, 0 }, { "jni_get_created_jvm_count", 1, jni_get_created_jvm_count_plc, 0 }, { "jni_ensure_jvm", 0, jni_ensure_jvm_plc, 0 }, { "jni_tag_to_iref", 2, jni_tag_to_iref_plc, 0 }, { "jni_hr_info", 4, jni_hr_info_plc, 0 }, { "jni_hr_table", 1, jni_hr_table_plc, 0 }, { "jni_byte_buf_length_to_codes", 3, jni_byte_buf_length_to_codes_plc, 0 }, { "jni_param_put", 4, jni_param_put_plc, 0 }, { "jni_alloc_buffer", 3, jni_alloc_buffer_plc, 0 }, { "jni_free_buffer", 1, jni_free_buffer_plc, 0 }, { "jni_fetch_buffer_value", 5, jni_fetch_buffer_value_plc, 0 }, { "jni_stash_buffer_value", 5, jni_stash_buffer_value_plc, 0 }, { "jni_void", 1, jni_void_0_plc, 0 }, { "jni_void", 2, jni_void_1_plc, 0 }, { "jni_void", 3, jni_void_2_plc, 0 }, { "jni_void", 4, jni_void_3_plc, 0 }, { "jni_void", 5, jni_void_4_plc, 0 }, { "jni_func", 2, jni_func_0_plc, 0 }, { "jni_func", 3, jni_func_1_plc, 0 }, { "jni_func", 4, jni_func_2_plc, 0 }, { "jni_func", 5, jni_func_3_plc, 0 }, { "jni_func", 6, jni_func_4_plc, 0 }, { "jpl_c_lib_version", 1, jpl_c_lib_version_1_plc, 0 }, { "jpl_c_lib_version", 4, jpl_c_lib_version_4_plc, 0 }, { "jpl_java_home", 1, jpl_c_java_home, 0 }, { NULL, 0, NULL, 0 } }; install_t jpl_install(void) { // PL_register_extensions( predspecs); PL_load_extensions( predspecs); } //=== JPL functions ================================================================================ static int create_pool_engines(void); static int jpl_num_initial_default_args(void) // used only once, by jpl_do_jpl_init() { int i; for ( i=0 ; default_args[i]!=NULL ; i++ ) { } return i; } // outcomes: // fail to find jpl.*, jpl.fli.* classes or to convert init args to String[]: exception, FALSE // all OK: TRUE // static bool jpl_do_jpl_init( // to be called once only, after PL init, before any JPL calls JNIEnv *env ) { jclass tc; // temporary class ref jobject ta; // temporary array ref char *msg; // error message for exceptions thrown here int i; // loop counter jobject to; // temporary (String) object ref if ( jpl_status != JPL_INIT_RAW ) // jpl init already attempted? (shouldn't happen) { DEBUG(1, Sdprintf( "[JPL: jpl_do_jpl_init() called AGAIN (skipping...)]\n")); return TRUE; } // prerequisites for setting initial default args into String[] dia: if ( (tc=(*env)->FindClass(env,"java/lang/String")) == NULL || (jString_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (ta=(*env)->NewObjectArray(env,jpl_num_initial_default_args(),jString_c,NULL)) == NULL || (dia=(*env)->NewGlobalRef(env,ta)) == NULL || ( (*env)->DeleteLocalRef(env,ta), FALSE) ) { msg = "jpl_do_jpl_init(): failed to find java.lang.String or create String[] dia"; goto err; } // copy the initial default args into String[] dia: for ( i=0 ; default_args[i]!=NULL ; i++ ) { if ( (to=(*env)->NewStringUTF(env,default_args[i])) == NULL ) { msg = "jpl_do_jpl_init(): failed to convert an initial default arg to a String"; goto err; } (*env)->SetObjectArrayElement(env,dia,i,to); // any errors/exceptions to be handled here? } if ( (tc=(*env)->FindClass(env,"jpl/JPLException")) == NULL || (jJPLException_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/term_t")) == NULL || (jTermT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/atom_t")) == NULL || (jAtomT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/functor_t")) == NULL || (jFunctorT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/fid_t")) == NULL || (jFidT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/predicate_t")) == NULL || (jPredicateT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/qid_t")) == NULL || (jQidT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/module_t")) == NULL || (jModuleT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/engine_t")) == NULL || (jEngineT_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/LongHolder")) == NULL || (jLongHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/PointerHolder")) == NULL || (jPointerHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/IntHolder")) == NULL || (jIntHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/DoubleHolder")) == NULL || (jDoubleHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/StringHolder")) == NULL || (jStringHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/ObjectHolder")) == NULL || (jObjectHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/fli/BooleanHolder")) == NULL || (jBooleanHolder_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/JRef")) == NULL || (jJRef_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (tc=(*env)->FindClass(env,"jpl/JBoolean")) == NULL || (jJBoolean_c=(*env)->NewGlobalRef(env,tc)) == NULL || ( (*env)->DeleteLocalRef(env,tc), FALSE) || (jLongHolderValue_f=(*env)->GetFieldID(env,jLongHolder_c,"value","J")) == NULL || (jPointerHolderValue_f=(*env)->GetFieldID(env,jPointerHolder_c,"value","J")) == NULL || (jIntHolderValue_f=(*env)->GetFieldID(env,jIntHolder_c,"value","I")) == NULL || (jDoubleHolderValue_f=(*env)->GetFieldID(env,jDoubleHolder_c,"value","D")) == NULL || (jStringHolderValue_f=(*env)->GetFieldID(env,jStringHolder_c,"value","Ljava/lang/String;")) == NULL || (jObjectHolderValue_f=(*env)->GetFieldID(env,jObjectHolder_c,"value","Ljava/lang/Object;")) == NULL || (jBooleanHolderValue_f=(*env)->GetFieldID(env,jBooleanHolder_c,"value","Z")) == NULL || (jJRefRef_f=(*env)->GetFieldID(env,jJRef_c,"ref","Ljava/lang/Object;")) == NULL || (jJBooleanValue_f=(*env)->GetFieldID(env,jJBoolean_c,"value","Z")) == NULL ) { msg = "jpl_do_jpl_init(): failed to find jpl.* or jpl.fli.* classes"; goto err; } DEBUG(1, Sdprintf( "[jpl_do_jpl_init() sets jpl_status = JPL_INIT_PVM_MAYBE, returns TRUE]\n")); jpl_status = JPL_INIT_PVM_MAYBE; return TRUE; err: jpl_status = JPL_INIT_JPL_FAILED; (*env)->ThrowNew(env,jJPLException_c,msg); return FALSE; } // prerequisite: // called only from jpl_test_pvm_init() and jpl_do_pvm_init() // outcomes: // error setting up post-PVM-init JPL state: throws exception, sets status = PVM_FAILED, returns FALSE // OK: sets status = OK, returns TRUE // static bool jpl_post_pvm_init( JNIEnv *env, int argc, char **argv ) { char *msg; jobject ta; int i; // Prolog VM is already initialised (by us or by other party) // retire default init args and set up actual init args: dia = NULL; // probably oughta delete (global) ref to former args... if ( (ta=(*env)->NewObjectArray(env,argc,jString_c,NULL)) == NULL || (aia=(*env)->NewGlobalRef(env,ta)) == NULL || ( (*env)->DeleteLocalRef(env,ta), FALSE) ) { msg = "jpl_post_pvm_init(): failed to copy actual init args"; goto err; } for ( i=0 ; iNewStringUTF(env,argv[i]); if ( to == NULL ) { msg = "jpl_post_pvm_init(): failed to convert actual PL init arg to String"; goto err; } (*env)->SetObjectArrayElement(env,aia,i,to); } if ( create_pool_engines() != 0 ) { msg = "jpl_post_pvm_init(): failed to create Prolog engine pool"; goto err; } jpl_status = JPL_INIT_OK; return TRUE; err: (*env)->ThrowNew( env, jJPLException_c, msg); jpl_status = JPL_INIT_PVM_FAILED; return FALSE; } // prerequisite: jpl_status != JPL_INIT_RAW // outcomes: // PVM is not (already) initialised -> FALSE // PVM is (already) initialised -> TRUE // error setting up post-PVM-init JPL state -> exception // static bool jpl_test_pvm_init( JNIEnv *env ) { char *msg; int argc; char **argv; // jobject ta; // int i; if ( jpl_status == JPL_INIT_RAW ) { msg = "jpl_test_pvm_init(): called while jpl_status == JPL_INIT_RAW"; goto err; } if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) { msg = "jpl_test_pvm_init(): initialisation has already failed"; goto err; } if ( jpl_status == JPL_INIT_OK ) { return TRUE; } if ( jpl_status == JPL_INIT_PVM_MAYBE ) { // we test this each time (if not already initialised) in case other foreign code inits the PVM: if ( !PL_is_initialised(&argc,&argv) ) // PVM not ready? { // jpl_status remains = JPL_INIT_PVM_MAYBE DEBUG(1, Sdprintf( "[pl_test_pvm_init(): PL is not yet initialised: returning FALSE]\n")); return FALSE; // already-active Prolog VM not found (NB not an exceptional condition) } else { DEBUG(1, Sdprintf( "[pl_test_pvm_init(): PL is already initialised: proceeding to jpl_post_pvm_init()]\n")); return jpl_post_pvm_init(env,argc,argv); // TRUE, FALSE or exception } } msg = "jpl_test_pvm_init(): unknown jpl_status value"; goto err; err: (*env)->ThrowNew( env, jJPLException_c, msg); jpl_status = JPL_INIT_PVM_FAILED; return FALSE; } // prerequisite: // jpl_status == JPL_INIT_PVM_MAYBE // outcomes: // successful PVM initialisation and subsequent JPL state setup -> TRUE // any error -> exception // static bool jpl_do_pvm_init( JNIEnv *env ) { char *msg; int argc; char **argv; int i; jstring arg; char *cp; // redundant prerequisites check: if ( jpl_status != JPL_INIT_PVM_MAYBE ) { msg = "jpl_do_pvm_init(): called while jpl_status != JPL_INIT_PVM_MAYBE"; goto err; } // copy current default init args into suitable form for PL_initialise(): if ( dia == NULL ) { msg = "jpl_do_pvm_init(): dia == NULL"; goto err; } argc = (*env)->GetArrayLength(env,dia); if ( argc <= 0 ) { msg = "jpl_do_pvm_init(): there are fewer than 1 default init args"; goto err; } if ( (argv=(char**)malloc((argc+1)*sizeof(char*))) == NULL ) { msg = "jpl_do_pvm_init(): malloc() failed for argv"; goto err; } for ( i=0 ; iGetObjectArrayElement(env,dia,i); cp = (char*)(*env)->GetStringUTFChars(env,arg,0); argv[i] = (char*)malloc(strlen(cp)+1); strcpy( argv[i], cp); DEBUG(1, Sdprintf( " argv[%d] = %s\n", i, argv[i])); (*env)->ReleaseStringUTFChars( env, arg, cp); } DEBUG(1, Sdprintf( " argv[%d] = NULL\n", argc)); argv[argc] = NULL; if ( !PL_initialise(argc,(char**)argv) ) // NB not (const char**) { msg = "jpl_do_pvm_init(): PL_initialise() failed"; goto err; } // *don't* free argv (must exist for lifetime of Prolog VM) return jpl_post_pvm_init(env,argc,argv); // TRUE, FALSE or exception err: jpl_status = JPL_INIT_PVM_FAILED; (*env)->ThrowNew( env, jJPLException_c, msg); return FALSE; } //=== initialisation-related native Java methods of jpl.fli.Prolog ================================= /* * Class: jpl_fli_PL * Method: get_default_init_args * Signature: ()[Ljava/lang/String; */ // // if not yet init then return default init args as String[] // if already init then return NULL // if already failed to init then throw an exception // JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_get_1default_1init_1args( JNIEnv *env, jclass jProlog ) { char *msg; jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) { msg = "jpl.fli.Prolog.set_default_init_args(): initialisation has already failed"; goto err; } return ( jpl_test_pvm_init(env) // if Prolog VM is initialised ? NULL // then default init args are no longer defined : dia // else here they are ) ; err: (*env)->ThrowNew( env, jJPLException_c, msg); return FALSE; } /* * Class: jpl_fli_PL * Method: set_default_init_args * Signature: ([Ljava/lang/String;)Z */ // // if the given jargs are null then throw an exception // if already failed to init then throw an exception // if not yet init then set default init args from jargs and return TRUE // if already init then return FALSE // JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_set_1default_1init_1args( JNIEnv *env, jclass jProlog, jobject jargs // oughta be proper array, perhaps zero-length ) { char *msg; jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary if ( jargs == NULL ) // improper call { msg = "jpl.fli.Prolog.set_default_init_args() called with NULL arg"; goto err; } if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) { msg = "jpl.fli.Prolog.set_default_init_args(): initialisation has already failed"; goto err; } if ( jpl_test_pvm_init(env) ) // if Prolog VM is initialised { return FALSE; // unable to set default init args (too late: PVM is already initialised) } else { dia = NULL; // probably oughta delete (global) (?) ref of former args... dia = (*env)->NewGlobalRef(env,jargs); return TRUE; // OK: default init args set to those provided } err: (*env)->ThrowNew( env, jJPLException_c, msg); return FALSE; } /* * Class: jpl_fli_PL * Method: get_actual_init_args * Signature: ()[Ljava/lang/String; */ // // if not yet init then return null // if already init then return actual init args as String[] // if already failed to init then throw an exception // JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_get_1actual_1init_1args( JNIEnv *env, jclass jProlog ) { char *msg; jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) { msg = "jpl.fli.Prolog.get_actual_init_args(): initialisation has already failed"; goto err; } return ( jpl_test_pvm_init(env) // check PL_initialise() and update local state as appropriate ? aia // here they are : NULL // PVM not (yet) initialised ); err: (*env)->ThrowNew( env, jJPLException_c, msg); return NULL; } /* * Class: jpl_fli_PL * Method: initialise * Signature: ()Z */ // // if already init then return FALSE // if already failed to init then throw an exception // else attempt to init and if success then return TRUE else throw an exception // JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_initialise( JNIEnv *env, jclass jProlog ) { char *msg; jpl_ensure_jpl_init( env); // lazily do "local" initialisations iff necessary if ( jpl_status==JPL_INIT_JPL_FAILED || jpl_status==JPL_INIT_PVM_FAILED ) { msg = "jpl.fli.Prolog.initialise(): initialisation has already failed"; goto err; } if ( jpl_test_pvm_init(env) ) { return FALSE; // PVM is already initialised } else { jpl_do_pvm_init( env); return jpl_test_pvm_init(env); } err: (*env)->ThrowNew( env, jJPLException_c, msg); return FALSE; } /* * Class: jpl_fli_PL * Method: halt * Signature: (I)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_halt( JNIEnv *env, jclass jProlog, jint jstatus ) { jpl_ensure_pvm_init(env); PL_halt( (int)jstatus); } //=== JPL utility functions ======================================================================== /*----------------------------------------------------------------------- * getLongValue * * Retrieves the value in a jpl.fli.LongHolder (or subclass) instance * * @param env Java environment * @param jlong_holder the LongHolder class instance, or null * @param lv address to write the retrieved (long) value * @return success? (the LongHolder was not null) *---------------------------------------------------------------------*/ static bool getLongValue( JNIEnv *env, jobject jlong_holder, long *lv ) { if ( jlong_holder == NULL ) { *lv = 0L; return FALSE; } else // Java compilation ensures it's a jpl.fli.LongHolder instance { *lv = (long)(*env)->GetLongField(env,jlong_holder,jLongHolderValue_f); return TRUE; } } /*----------------------------------------------------------------------- * getPointerValue * * Retrieves the value in a jpl.fli.PointerHolder instance * * @param env Java environment * @param jpointer_holder the PointerHolder class instance, or null * @param pv address to write the retrieved (pointer) value * @return success? (the PointerHolder was not null) *---------------------------------------------------------------------*/ static bool getPointerValue( // sets pv to jpointer_holder's .value_ (and succeeds), else sets it to NULL (and fails) JNIEnv *env, jobject jpointer_holder, pointer *pv ) { if ( jpointer_holder == NULL ) { *pv = (pointer)NULL; return FALSE; } else // Java compilation ensures it's a jpl.fli.PointerHolder instance { *pv = (pointer)(*env)->GetLongField(env,jpointer_holder,jPointerHolderValue_f); return TRUE; } } /*----------------------------------------------------------------------- * setPointerValue * * Sets the value in a jpl.fli.Pointer class instance (unless it's null) * to the supplied value (maybe 0L) * * @param env Java environment * @param jpointer_holder the PointerHolder class instance, or null * @param pv the new (pointer) value *---------------------------------------------------------------------*/ static bool setPointerValue( JNIEnv *env, jobject jpointer_holder, pointer pv ) { return jpointer_holder != NULL && ( (*env)->SetLongField(env,jpointer_holder,jPointerHolderValue_f,(long)pv), TRUE ) ; } /*----------------------------------------------------------------------- * setIntValue * * Sets the value in a Java IntHolder class instance (unless it's null) * to the supplied value * * @param env Java environment * @param jint_holder the IntHolder class instance, or null * @param iv the new (int) value *---------------------------------------------------------------------*/ static bool setIntValue( JNIEnv *env, jobject jint_holder, int iv ) { return jint_holder != NULL && ( (*env)->SetIntField(env,jint_holder,jIntHolderValue_f,iv), TRUE ) ; } /*----------------------------------------------------------------------- * setLongValue * * Sets the value in a Java LongHolder class instance (unless it's null) * to the supplied value (maybe 0L) * * @param env Java environment * @param jlong_holder the LongHolder class instance, or null * @param lv the new (long) value *---------------------------------------------------------------------*/ static bool setLongValue( JNIEnv *env, jobject jlong_holder, long lv ) { return jlong_holder != NULL && ( (*env)->SetLongField(env,jlong_holder,jLongHolderValue_f,lv), TRUE ) ; } /*----------------------------------------------------------------------- * setDoubleValue * * Sets the value in a Java DoubleHolder class instance (unless it's null) * to the supplied value * * @param env Java environment * @param jdouble_holder the DoubleHolder class instance, or null * @param dv the new (double) value *---------------------------------------------------------------------*/ static bool setDoubleValue( JNIEnv *env, jobject jdouble_holder, double dv ) { return jdouble_holder != NULL && ( (*env)->SetDoubleField(env,jdouble_holder,jDoubleHolderValue_f,dv), TRUE ) ; } /*----------------------------------------------------------------------- * setStringValue * * Sets the value in a Java StringHolder class instance (unless it's null) * to the supplied value (maybe null) * * @param env Java environment * @param jstring_holder the StringHolder class instance, or null * @param sv the new (jstring) value *---------------------------------------------------------------------*/ static bool setStringValue( JNIEnv *env, jobject jstring_holder, jstring sv ) { return jstring_holder != NULL && ( (*env)->SetObjectField(env,jstring_holder,jStringHolderValue_f,sv), TRUE ) ; } /*----------------------------------------------------------------------- * setObjectValue * * Sets the value in a Java ObjectHolder class instance (unless it's null) * to the supplied value (maybe null) * * @param env Java environment * @param jobject_holder the ObjectHolder class instance, or null * @param ref the new (jobject) value *---------------------------------------------------------------------*/ static bool setObjectValue( JNIEnv *env, jobject jobject_holder, jobject ref ) { return jobject_holder != NULL && ( (*env)->SetObjectField(env,jobject_holder,jObjectHolderValue_f,ref), TRUE ) ; } /*----------------------------------------------------------------------- * setBooleanValue * * Sets the .value field of a Java BooleanHolder class instance (unless it's null) * to the supplied jboolean value * * @param env Java environment * @param jboolean_holder the BooleanHolder class instance, or null * @param jb the new (jboolean) value *---------------------------------------------------------------------*/ static bool setBooleanValue( JNIEnv *env, jobject jboolean_holder, jboolean jb ) { return jboolean_holder != NULL && ( (*env)->SetBooleanField(env,jboolean_holder,jBooleanHolderValue_f,jb), TRUE ) ; } /*----------------------------------------------------------------------- * updateAtomValue * * Updates the value in a Java atom_t class instance (unless it's null) * to the supplied value (maybe 0L); unregisters and registers old and new * atom references as appropriate. NB atom_t extends LongHolder. * * @param env Java environment * @param jatom_holder the atom_t class instance, or null * @param atom2 the new atom reference *---------------------------------------------------------------------*/ static bool updateAtomValue( JNIEnv *env, jobject jatom_holder, atom_t atom2 // new value (perhaps 0L (?)) ) { atom_t atom1; // old value (perhaps 0L (?)) if ( jatom_holder == NULL ) { return FALSE; } else { atom1 = (atom_t)(*env)->GetLongField(env,jatom_holder,jLongHolderValue_f); if ( atom1 != 0L ) { PL_unregister_atom( atom1); } (*env)->SetLongField(env,jatom_holder,jLongHolderValue_f,(long)atom2); if ( atom2 != 0L ) { PL_register_atom( atom2); } return TRUE; } } //=== Java-wrapped SWI-Prolog FLI functions ======================================================== /* * Class: jpl_fli_PL * Method: new_term_ref * Signature: ()Ljpl/fli/term_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1term_1ref( JNIEnv *env, jclass jProlog ) { jobject rval; return ( jpl_ensure_pvm_init(env) && (rval=(*env)->AllocObject(env,jTermT_c)) != NULL && setLongValue(env,rval,(long)PL_new_term_ref()) ? rval : NULL ) ; } /* * Class: jpl_fli_PL * Method: new_term_refs * Signature: (I)Ljpl/fli/term_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1term_1refs( JNIEnv *env, jclass jProlog, jint jn ) { jobject rval; term_t trefs; DEBUG(1, Sdprintf( ">new_term_refs(env=%lu,jProlog=%lu,jn=%lu)...\n", (long)env, (long)jProlog, (long)jn)); return ( jpl_ensure_pvm_init(env) && jn >= 0 // I hope PL_new_term_refs(0) is defined [ISSUE] && (rval=(*env)->AllocObject(env,jTermT_c)) != NULL && ( trefs=PL_new_term_refs((int)jn), TRUE ) && setLongValue(env,rval,(long)trefs) && ( DEBUG(1, Sdprintf(" ok: stashed trefs=%ld into new term_t object\n",(long)trefs)), TRUE ) ? rval : NULL ) ; } /* * Class: jpl_fli_PL * Method: copy_term_ref * Signature: (Ljpl/fli/term_t;)Ljpl/fli/term_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_copy_1term_1ref( JNIEnv *env, jclass jProlog, jobject jfrom ) { jobject rval; term_t term; term_t term2; return ( jpl_ensure_pvm_init(env) // && jfrom != NULL // redundant: getLongValue checks this && getLongValue(env,jfrom,(long*)&term) // SWI RM implies must be non-null && (rval=(*env)->AllocObject(env,jTermT_c)) != NULL && ( (term2=PL_copy_term_ref(term)) , TRUE ) // SWI RM -> always succeeds && setLongValue(env,rval,(long)term2) ? rval : NULL // oughta warn of failure? ) ; } /* * Class: jpl_fli_PL * Method: reset_term_refs * Signature: (Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_reset_1term_1refs( JNIEnv *env, jclass jProlog, jobject jafter ) { term_t term; if ( jpl_ensure_pvm_init(env) // && jafter != NULL // redundant: getLongValue checks this && getLongValue(env,jafter,&term) // SWI RM -> oughta be non-null ) { PL_reset_term_refs( term); // void; SWI RM -> "always succeeds" } } /* * Class: jpl_fli_PL * Method: new_atom * Signature: (Ljava/lang/String;)Ljpl/fli/atom_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1atom( JNIEnv *env, jclass jProlog, jstring jname ) { const char *name; atom_t atom; jobject rval; return ( jpl_ensure_pvm_init(env) && jname != NULL && (name=(*env)->GetStringUTFChars(env,jname,NULL)) != NULL // no exceptions && ( (atom=PL_new_atom(name)) , TRUE ) // SWI RM p138 -> "always succeeds"; incs ref count && ( (*env)->ReleaseStringUTFChars(env,jname,name) , TRUE ) // void; no exceptions && (rval=(*env)->AllocObject(env,jAtomT_c)) != NULL // doesn't call any constructor && setLongValue(env,rval,(long)atom) ? rval : NULL // oughta warn of failure? ) ; } /* * Class: jpl_fli_PL * Method: atom_chars * Signature: (Ljpl/fli/atom_t;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL // the local ref goes out of scope, Java_jpl_fli_Prolog_atom_1chars( // but the string itself doesn't JNIEnv *env, jclass jProlog, jobject jatom ) { atom_t atom; jstring lref; // jstring gref; const char *s; return ( jpl_ensure_pvm_init(env) && getLongValue(env,jatom,(long*)&atom) // checks jatom != null && (s=PL_atom_chars(atom)) != NULL // SWI RM -> "always succeeds" && (lref=(*env)->NewStringUTF(env,s)) != NULL // out-of-memory -> NULL, exception ? lref : NULL ) ; } /* * Class: jpl_fli_PL * Method: new_functor * Signature: (Ljpl/fli/atom_t;I)Ljpl/fli/functor_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1functor( JNIEnv *env, jclass jProlog, jobject jatom, // read-only jint jarity ) { term_t atom; functor_t functor; jobject rval; return ( jpl_ensure_pvm_init(env) && jarity >= 0 && getLongValue(env,jatom,(long*)&atom) // checks jatom isn't null && (rval=(*env)->AllocObject(env,jFunctorT_c)) != NULL && (functor=PL_new_functor(atom,(int)jarity)) != 0L && setLongValue(env,rval,(long)functor) ? rval : NULL // oughta warn of failure? ) ; } /* * Class: jpl_fli_PL * Method: functor_name * Signature: (Ljpl/fli/functor_t;)Ljpl/fli/atom_t; */ JNIEXPORT jobject JNICALL // returns a new atom_t, containing a newly-registered atom ref Java_jpl_fli_Prolog_functor_1name( JNIEnv *env, jclass jProlog, jobject jfunctor ) { functor_t functor; atom_t atom; jobject rval; return ( jpl_ensure_pvm_init(env) && getLongValue(env,jfunctor,(long*)&functor) // SWI RM -> must be a real functor && (atom=PL_functor_name(functor)) != 0L // unlike PL_new_atom, doesn't register the ref && (rval=(*env)->AllocObject(env,jAtomT_c)) != NULL // doesn't call any constructor && setLongValue(env,rval,(long)atom) && ( PL_register_atom(atom), TRUE ) // register this reference ? rval : NULL // oughta warn of failure? ) ; } /* * Class: jpl_fli_PL * Method: functor_arity * Signature: (Ljpl/fli/functor_t;)I */ JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_functor_1arity( JNIEnv *env, jclass jProlog, jobject jfunctor ) { functor_t functor; return ( jpl_ensure_pvm_init(env) && getLongValue(env,jfunctor,(long*)&functor) // checks jfunctor isn't null ? PL_functor_arity(functor) : -1 // oughta warn of failure? ) ; } //=== from "5.6.3 Analysing terms via the foreign interface", "Testing the Type of a term" ======== // not needed: // PL_register_atom() /* * Class: jpl_fli_PL * Method: term_type * Signature: (Ljpl/fli/term_t;)I */ JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_term_1type( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return ( jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null ? PL_term_type(term) : -1 // i.e. when jterm is null ) ; } /* * Class: jpl_fli_PL * Method: is_variable * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1variable( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_variable(term) ; } /* * Class: jpl_fli_PL * Method: is_atom * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1atom( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_atom(term) ; } /* * Class: jpl_fli_PL * Method: is_integer * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1integer( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_integer(term) ; } /* * Class: jpl_fli_PL * Method: is_float * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1float( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_float(term) ; } /* * Class: jpl_fli_PL * Method: is_compound * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1compound( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_compound(term) ; } /* * Class: jpl_fli_PL * Method: is_functor * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1functor( JNIEnv *env, jclass jProlog, jobject jterm, jobject jfunctor ) { term_t term; functor_t functor; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && getLongValue(env,jfunctor,(long*)&functor) // checks jfunctor isn't null && PL_is_functor(term,functor) ; } /* * Class: jpl_fli_PL * Method: is_list * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1list( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_list(term) ; } /* * Class: jpl_fli_PL * Method: is_atomic * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1atomic( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_atomic(term) ; } /* * Class: jpl_fli_PL * Method: is_number * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_is_1number( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks jterm isn't null && PL_is_number(term) ; } //=== from "5.6.3 Analysing Terms via the Foreign Interface: Reading data from a term" ============ // not yet mapped: register_atom() // unregister_atom() /* * Class: jpl_fli_PL * Method: get_atom * Signature: (Ljpl/fli/term_t;Ljpl/fli/atom_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1atom( JNIEnv *env, jclass jProlog, jobject jterm, // read jobject jatom // update ) { term_t term; atom_t atom; return jpl_ensure_pvm_init(env) && jatom != NULL // don't call PL_get_atom if jatom is null && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL && PL_get_atom(term,&atom) // iff term is an atom; doesn't register the ref && updateAtomValue(env,jatom,atom) // unreg old ref (if any); reg new ref (if any) ; } /* * Class: jpl_fli_PL * Method: get_atom_chars * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1atom_1chars( JNIEnv *env, jclass jProlog, jobject jterm, jobject jstring_holder ) { term_t term; char *s; jstring string; return jpl_ensure_pvm_init(env) && jstring_holder != NULL // don't call PL_get_atom_chars if this is null && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL && PL_get_atom_chars(term,&s) // fails (usefully) if term is not an atom && (string=(*env)->NewStringUTF(env,s)) != NULL // OK as local ref... && setStringValue(env,jstring_holder,string) // ...when sent straight back to JVM ; } /* * Class: jpl_fli_PL * Method: get_string_chars * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1string_1chars( JNIEnv *env, jclass jProlog, jobject jterm, jobject jstring_holder ) { term_t term; char *s; int n; jstring string; return jpl_ensure_pvm_init(env) && jstring_holder != NULL // don't call PL_get_atom_chars if this is null && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL && PL_get_string_chars(term,&s,&n) // fails (usefully) if term is not a string && (string=(*env)->NewStringUTF(env,s)) != NULL // OK as local ref... && setStringValue(env,jstring_holder,string) // ...when sent straight back to JVM ; } /* * Class: jpl_fli_PL * Method: get_chars * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;I)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1chars( // withdraw this? JNIEnv *env, jclass jProlog, jobject jterm, jobject jstring_holder, jint jflags ) { term_t term; char *s; jstring string; return jpl_ensure_pvm_init(env) && jstring_holder != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL && PL_get_chars(term,&s,(unsigned)jflags) && (string=(*env)->NewStringUTF(env,s)) != NULL && setStringValue(env,jstring_holder,string) // OK as local ref? ; } /* * Class: jpl_fli_PL * Method: get_list_chars * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;I)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1list_1chars( // withdraw this? JNIEnv *env, jclass jProlog, jobject jterm, jobject jstring_holder, jint jflags ) { term_t term; char *s; jstring string; return jpl_ensure_pvm_init(env) && jstring_holder != NULL // don't call PL_get_list_chars if this is null && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && PL_get_list_chars(term,&s,(unsigned)jflags) && (string=(*env)->NewStringUTF(env,s)) != NULL && setStringValue(env,jstring_holder,string) // OK as local ref? ; } /* * Class: jpl_fli_PL * Method: get_integer * Signature: (Ljpl/fli/term_t;Ljpl/fli/IntHolder;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1integer( JNIEnv *env, jclass jProlog, jobject jterm, jobject jint_holder ) { term_t term; int i; return jpl_ensure_pvm_init(env) && jint_holder != NULL // don't call PL_get_integer if this is null && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && PL_get_integer(term,&i) && setIntValue(env,jint_holder,i) ; } /* * Class: jpl_fli_PL * Method: get_pointer * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1pointer( JNIEnv *env, jclass jProlog, jobject jterm, jobject jpointer ) { term_t term; pointer ptr; return jpl_ensure_pvm_init(env) && jpointer != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && PL_get_pointer(term,(void**)&ptr) && setPointerValue(env,jpointer,ptr) ; } /* * Class: jpl_fli_PL * Method: get_float * Signature: (Ljpl/fli/term_t;Ljpl/fli/DoubleHolder;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1float( JNIEnv *env, jclass jProlog, jobject jterm, jobject jdouble_holder ) { term_t term; double d; return jpl_ensure_pvm_init(env) && jdouble_holder != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && PL_get_float(term,&d) && setDoubleValue(env,jdouble_holder,d) ; } /* * Class: jpl_fli_PL * Method: get_jref * Signature: (Ljpl/fli/term_t;Ljpl/fli/ObjectHolder;)Z */ // added 26/Jan/2004 untested... JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1jref( JNIEnv *env, jclass jProlog, jobject jterm, jobject jobject_holder ) { term_t term; jobject ref; char *cp; functor_t fn; term_t a1; atom_t a; return jpl_ensure_pvm_init(env) && jobject_holder != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && JNI_term_to_ref(term,ref) && setObjectValue(env,jobject_holder,ref) ; } /* * Class: jpl_fli_PL * Method: get_jboolean * Signature: (Ljpl/fli/term_t;Ljpl/fli/BooleanHolder;)Z */ // called with a term_t holder and a boolean holder; // if the term_t is @(false) or @(true), sets the boolean value accordingly and succeeds, // else fails // added 26/Jan/2004 untested... JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1jboolean( JNIEnv *env, jclass jProlog, jobject jterm, jobject jboolean_holder ) { term_t term; // temp for term ref extracted from the passed-in "term_t holder" jboolean b; // temp for boolean by-ref result from JNI_term_to_jboolean(+,-) functor_t fn; // temp for JNI_term_to_jboolean(+,-) term_t a1; // " atom_t a; // " return jpl_ensure_pvm_init(env) // merge these please && jni_ensure_jvm() // " && jboolean_holder != NULL // fail if no boolean holder is passed && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && JNI_term_to_jboolean(term,b) && setBooleanValue(env,jboolean_holder,b) ; } /* * Class: jpl_fli_PL * Method: get_jpl_term * Signature: (Ljpl/fli/term_t;Ljpl/fli/ObjectHolder;)Z */ // // added 18/Jun/2004 PS untested... // succeeds iff jterm is one of the special JPL terms, // i.e. @(false), @(true), @(null) or @(Tag) e.g. @('J#0123456789'), // stashing a corresponding jpl.JBoolean or jpl.JRef into the object holder // JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1jpl_1term( JNIEnv *env, jclass jProlog, jobject jterm, // a jpl.fli.term_t instance jobject jobject_holder // a jpl.fli.ObjectHolder instance ) { term_t term; // the Prolog term referred to by jterm functor_t fn; // the term's functor term_t a1; // the term's first & only arg, if it has one atom_t a; // the atom which is the term's only arg jobject obj; // a JBoolean or JRef to be returned jobject ref; // the object referred to by Tag return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) && PL_get_functor(term,&fn) // succeeds iff jterm is atom or compound && fn == JNI_functor_at_1 // jterm is @(Something) && ( a1 = PL_new_term_ref(), PL_get_arg(1,term,a1) // a1 is that Something ) && PL_get_atom(a1,&a) // succeeds iff a1 is an atom && ( a == JNI_atom_null // Something == null ? (obj=(*env)->AllocObject(env,jJRef_c)) != NULL && ((*env)->SetObjectField(env,obj,jJRefRef_f,NULL), TRUE) && setObjectValue(env,jobject_holder,obj) : a == JNI_atom_true // Something == true ? (obj=(*env)->AllocObject(env,jJBoolean_c)) != NULL && ((*env)->SetBooleanField(env,obj,jJBooleanValue_f,TRUE), TRUE) && setObjectValue(env,jobject_holder,obj) : a == JNI_atom_false // Something == false ? (obj=(*env)->AllocObject(env,jJBoolean_c)) != NULL && ((*env)->SetBooleanField(env,obj,jJBooleanValue_f,FALSE), TRUE) && setObjectValue(env,jobject_holder,obj) : jni_tag_to_iref(a,(int*)&ref) // convert digits to int ? (obj=(*env)->AllocObject(env,jJRef_c)) != NULL && ((*env)->SetObjectField(env,obj,jJRefRef_f,ref), TRUE) && setObjectValue(env,jobject_holder,obj) : FALSE // jterm is not a special JPL structure ); } /* * Class: jpl_fli_PL * Method: get_functor * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1functor( JNIEnv *env, jclass jProlog, jobject jterm, jobject jfunctor ) { term_t term; functor_t functor; return jpl_ensure_pvm_init(env) && jfunctor != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && PL_get_functor(term,&functor) && setLongValue(env,jfunctor,(long)functor) ; } /* * Class: jpl_fli_PL * Method: get_name_arity * Signature: (Ljpl/fli/term_t;Ljpl/fli/StringHolder;Ljpl/fli/IntHolder;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1name_1arity( JNIEnv *env, jclass jProlog, jobject jterm, jobject jname_holder, // was atom_t, now StringHolder jobject jarity_holder ) { term_t term; atom_t atom; int arity; char *name; jstring jname; return jpl_ensure_pvm_init(env) && jname_holder != NULL // don't proceed if this holder is null && jarity_holder != NULL // don't proceed if this holder is null && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && PL_get_name_arity(term,&atom,&arity) // no need to register transient atom ref && ( name=(char*)PL_atom_chars(atom) , TRUE ) // from const char* && (jname=(*env)->NewStringUTF(env,name)) != NULL && setStringValue(env,jname_holder,jname) // stash String ref in holder && setIntValue(env,jarity_holder,arity) // stash arity value in holder ; } /* * Class: jpl_fli_PL * Method: get_module * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1module( JNIEnv *env, jclass jProlog, jobject jterm, // read jobject jmodule // update ) { term_t term; module_t module; return jpl_ensure_pvm_init(env) && jmodule != NULL // don't proceed if this holder is null && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && PL_get_module(term,&module) && setPointerValue(env,jmodule,(pointer)module) ; } /* * Class: jpl_fli_PL * Method: get_arg * Signature: (ILjpl/fli/term_t;Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1arg( JNIEnv *env, jclass jProlog, jint jindex, jobject jterm, jobject jarg ) { term_t term; term_t arg; return jpl_ensure_pvm_init(env) && jarg != NULL // don't proceed if this holder is null && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && ( arg=PL_new_term_ref() , TRUE ) // Fred used jarg's original term ref (?) && PL_get_arg(jindex,term,arg) && setLongValue(env,jarg,(long)arg) ; } //=== from "5.6.3 Analysing Terms via the Foreign Interface: Reading a list" ====================== // not yet mapped: // get_atom_nchars() // get_atom_nchars() // get_list_nchars() // get_nchars() // put_atom_nchars() // put_list_ncodes() // put_list_nchars() // unify_atom_nchars() // unify_list_ncodes() // unify_list_nchars() /* * Class: jpl_fli_PL * Method: get_list * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1list( JNIEnv *env, jclass jProlog, jobject jlist, jobject jhead, jobject jtail ) { term_t list; term_t head = PL_new_term_ref(); term_t tail = PL_new_term_ref(); return jpl_ensure_pvm_init(env) && jhead != NULL && jtail != NULL && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null && PL_get_list(list,head,tail) && setLongValue(env,jhead,(long)head) && setLongValue(env,jtail,(long)tail) ; } /* * Class: jpl_fli_PL * Method: get_head * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1head( JNIEnv *env, jclass jProlog, jobject jlist, jobject jhead ) { term_t list; term_t head = PL_new_term_ref(); return jpl_ensure_pvm_init(env) && jhead != NULL && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null && PL_get_head(list,head) && setLongValue(env,jhead,(long)head) ; } /* * Class: jpl_fli_PL * Method: get_tail * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1tail( JNIEnv *env, jclass jProlog, jobject jlist, jobject jtail ) { term_t list; term_t tail = PL_new_term_ref(); return jpl_ensure_pvm_init(env) && jtail != NULL && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null && PL_get_tail(list,tail) && setLongValue(env,jtail,(long)tail) ; } /* * Class: jpl_fli_PL * Method: get_nil * Signature: (Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_get_1nil( // redundant: tests term == '[]' JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; return jpl_ensure_pvm_init(env) && jterm != NULL && getLongValue(env,jterm,(long*)&term) && PL_get_nil(term) ; } //=== from "5.6.4 Constructing terms" ============================================================== // these methods perhaps oughta return jboolean, false iff given object is null... /* * Class: jpl_fli_PL * Method: put_variable * Signature: (Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1variable( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; if ( jpl_ensure_pvm_init(env) // may throw exception but cannot fail && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null ) { PL_put_variable(term); } } /* * Class: jpl_fli_PL * Method: put_atom * Signature: (Ljpl/fli/term_t;Ljpl/fli/atom_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1atom( JNIEnv *env, jclass jProlog, jobject jterm, jobject jatom ) { term_t term; atom_t atom; if ( jpl_ensure_pvm_init(env) && jatom != NULL // don't proceed if this holder is null && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null ) { getLongValue( env, jterm, (long*)&term); getLongValue( env, jatom, (long*)&atom); // no need to register this transient atom ref PL_put_atom( term, atom); } } /* * Class: jpl_fli_PL * Method: put_atom_chars * Signature: (Ljpl/fli/term_t;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1atom_1chars( // no atom refs involved here JNIEnv *env, jclass jProlog, jobject jterm, jstring jchars ) { term_t term; const char *chars; if ( jpl_ensure_pvm_init(env) && jchars != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && (chars=(*env)->GetStringUTFChars(env,jchars,NULL)) != NULL // is this return idiom OK? [ISSUE] ) { PL_put_atom_chars( term, chars); (*env)->ReleaseStringUTFChars( env, jchars, chars); } } /* * Class: jpl_fli_PL * Method: put_list_chars * Signature: (Ljpl/fli/term_t;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1list_1chars( JNIEnv *env, jclass jProlog, jobject jterm, jstring jchars ) { term_t term; const char *chars; if ( jpl_ensure_pvm_init(env) && jchars != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && (chars=(*env)->GetStringUTFChars(env,jchars,NULL)) != NULL // is this return idiom OK? [ISSUE] ) { PL_put_list_chars( term, chars); (*env)->ReleaseStringUTFChars( env, jchars, chars); } } /* * Class: jpl_fli_PL * Method: put_integer * Signature: (Ljpl/fli/term_t;J)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1integer( JNIEnv *env, jclass jProlog, jobject jterm, jlong ji // why jlong? ) { term_t term; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null ) { PL_put_integer( term, (int)ji); // ??? } } /* * Class: jpl_fli_PL * Method: put_pointer * Signature: (Ljpl/fli/term_t;Ljpl/fli/Pointer;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1pointer( JNIEnv *env, jclass jProlog, jobject jterm, jobject jpointer ) { term_t term; pointer ptr; if ( jpl_ensure_pvm_init(env) && jpointer != NULL && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && getPointerValue(env,jpointer,&ptr) ) { PL_put_pointer( term, (void*)ptr); } } /* * Class: jpl_fli_PL * Method: put_float * Signature: (Ljpl/fli/term_t;D)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1float( JNIEnv *env, jclass jProlog, jobject jterm, jdouble jf ) { term_t term; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null ) { PL_put_float( term, jf); } } /* * Class: jpl_fli_PL * Method: put_functor * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1functor( JNIEnv *env, jclass jProlog, jobject jterm, jobject jfunctor ) { term_t term; functor_t functor; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && getLongValue(env,jfunctor,(long*)&functor) // checks that jfunctor isn't null ) { PL_put_functor( term, functor); } } /* * Class: jpl_fli_PL * Method: put_list * Signature: (Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1list( JNIEnv *env, jclass jProlog, jobject jlist ) { term_t term; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jlist,(long*)&term) // checks that jlist isn't null ) { PL_put_list( term); } } /* * Class: jpl_fli_PL * Method: put_nil * Signature: (Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1nil( JNIEnv *env, jclass jProlog, jobject jlist ) { term_t term; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jlist,(long*)&term) // checks that jlist isn't null ) { PL_put_nil( term); } } /* * Class: jpl_fli_PL * Method: put_term * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1term( JNIEnv *env, jclass jProlog, jobject jterm1, jobject jterm2 ) { term_t term1; term_t term2; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jterm1,(long*)&term1) // checks that jterm1 isn't null && getLongValue(env,jterm2,(long*)&term2) // checks that jterm2 isn't null ) { PL_put_term( term1, term2); } } /* * Class: jpl_fli_PL * Method: put_jref * Signature: (Ljpl/fli/term_t;Ljava/lang/Object;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1jref( JNIEnv *env, jclass jProlog, jobject jterm, jobject jref ) { term_t term; jobject j; // temp for JNI_jobject_to_term(+,-) atom_t a; // " int i; // " DEBUG(1, Sdprintf( ">put_ref(env=%lu,jProlog=%lu,jterm=%lu,jref=%lu)...\n", env, jProlog, jterm, jref)); ( jpl_ensure_pvm_init(env) // combine these two please && jni_ensure_jvm() // " && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && JNI_jobject_to_term(jref,term) // assumes term is var; OK if jref == null ); } /* * Class: jpl_fli_PL * Method: put_jboolean * Signature: (Ljpl/fli/term_t;Z)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1jboolean( JNIEnv *env, jclass jProlog, jobject jterm, jboolean jbool ) { term_t term; // temp for term ref from within the passed "term holder" DEBUG(1, Sdprintf( ">put_jboolean(env=%lu,jProlog=%lu,jterm=%lu,jbool=%u)...\n", env, jProlog, jterm, jbool)); ( jpl_ensure_pvm_init(env) // combine these two please && jni_ensure_jvm() // " && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && JNI_jboolean_to_term(jbool,term) // assumes term is var ); } /* * Class: jpl_fli_PL * Method: put_jvoid * Signature: (Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_put_1jvoid( JNIEnv *env, jclass jProlog, jobject jterm ) { term_t term; // temp for term ref from within the passed "term holder" DEBUG(1, Sdprintf( ">put_jvoid(env=%lu,jProlog=%lu,jterm=%lu)...\n", env, jProlog, jterm)); ( jpl_ensure_pvm_init(env) // combine these two please && jni_ensure_jvm() // " && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && JNI_unify_void(term) // assumes term is var ); } /* * Class: jpl_fli_PL * Method: cons_functor_v * Signature: (Ljpl/fli/term_t;Ljpl/fli/functor_t;Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_cons_1functor_1v( JNIEnv *env, jclass jProlog, jobject jterm, jobject jfunctor, jobject jterm0 ) { term_t term; functor_t functor; term_t term0; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks that jterm isn't null && getLongValue(env,jfunctor,(long*)&functor) // checks that jfunctor isn't null && getLongValue(env,jterm0,(long*)&term0) // checks that jterm0 isn't null ) { PL_cons_functor_v( term, functor, term0); } } /* * Class: jpl_fli_PL * Method: cons_list * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;Ljpl/fli/term_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_cons_1list( JNIEnv *env, jclass jProlog, jobject jlist, jobject jhead, jobject jtail ) { term_t list; term_t head; term_t tail; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jlist,(long*)&list) // checks that jlist isn't null && getLongValue(env,jhead,(long*)&head) // checks that jhead isn't null && getLongValue(env,jtail,(long*)&tail) // checks that jtail isn't null ) { PL_cons_list( list, head, tail); } } //=== from "5.6.5 Unifying data" ================================================================== // not yet mapped: // unify_atom() // unify_atom_chars() // unify_list_chars() // unify_integer() // unify_float() // unify_pointer() // unify_functor() // unify_list() // unify_nil() // unify_arg() // unify_term() // chars_to_term() // quote() // /* // * Class: jpl_fli_PL // * Method: unify // * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)I // */ // JNIEXPORT jint JNICALL // Java_jpl_fli_Prolog_unify( // JNIEnv *env, // jclass jProlog, // jobject jterm1, // jobject jterm2 // ) // { // term_t term1; // term_t term2; // // if ( jpl_ensure_pvm_init(env) // && getLongValue(env,jterm1,(long*)&term1) // checks that jterm1 isn't null // && getLongValue(env,jterm2,(long*)&term2) // checks that jterm2 isn't null // ) // { // PL_unify( term1, term2); // } // } //=== from "5.6.7 Discarding data" (none of these are (yet) used in LLI or HLI) =================== /* * Class: jpl_fli_PL * Method: open_foreign_frame * Signature: ()Ljpl/fli/fid_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_open_1foreign_1frame( JNIEnv *env, jclass jProlog ) { jobject rval; if ( jpl_ensure_pvm_init(env) && (rval=(*env)->AllocObject(env,jFidT_c)) != NULL // get a new fid_t object && setLongValue(env,rval,(long)PL_open_foreign_frame()) // open a frame only if alloc succeeds ) { return rval; } else { return NULL; } } /* * Class: jpl_fli_PL * Method: close_foreign_frame * Signature: (Ljpl/fli/fid_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_close_1foreign_1frame( JNIEnv *env, jclass jProlog, jobject jfid ) { fid_t fid; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jfid,(long*)&fid) // checks that jfid isn't null ) { PL_close_foreign_frame(fid); } } /* * Class: jpl_fli_PL * Method: discard_foreign_frame * Signature: (Ljpl/fli/fid_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_discard_1foreign_1frame( JNIEnv *env, jclass jProlog, jobject jfid ) { fid_t fid; if ( jpl_ensure_pvm_init(env) && getLongValue(env,jfid,(long*)&fid) // checks that jfid isn't null ) { PL_discard_foreign_frame(fid); } } //=== from "5.6.6 Calling Prolog from C: Predicate references" ==================================== /* * Class: jpl_fli_PL * Method: pred * Signature: (Ljpl/fli/functor_t;Ljpl/fli/module_t;)Ljpl/fli/predicate_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_pred( JNIEnv *env, jclass jProlog, jobject jfunctor, jobject jmodule ) { functor_t functor; module_t module; predicate_t predicate; jobject rval; return ( jpl_ensure_pvm_init(env) && getLongValue(env,jfunctor,(long*)&functor) // checks that jfunctor isn't null && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // if jmodule is null then module = NULL && ( (predicate=PL_pred(functor,module)) , TRUE ) // module==NULL is OK (?) [ISSUE] && (rval=(*env)->AllocObject(env,jPredicateT_c)) != NULL && setPointerValue(env,rval,(pointer)predicate) && ( DEBUG(1, Sdprintf("[pred module = %s]\n",(module==NULL?"(null)":PL_atom_chars(PL_module_name(module))))), TRUE ) ? rval : NULL // oughta warn of failure? ) ; } /* * Class: jpl_fli_PL * Method: predicate * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljpl/fli/predicate_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_predicate( JNIEnv *env, jclass jProlog, jstring jname, jint jarity, jstring jmodule ) { const char *name; const char *module; // NOT module_t as in JPL 1.0.1 predicate_t predicate; jobject rval; DEBUG(1, Sdprintf(">predicate(env=%lu,jProlog=%lu,jname=%lu,jarity=%lu,jmodule=%lu)...\n", (long)env, (long)jProlog, (long)jname, (long)jarity, (long)jmodule)); return ( jpl_ensure_pvm_init(env) && jname != NULL && jarity >= 0 && (name=(*env)->GetStringUTFChars(env,jname,0)) != NULL && ( jmodule != NULL ? (module=(*env)->GetStringUTFChars(env,jmodule,0)) != NULL : ( module=NULL, TRUE ) ) && ( (predicate=PL_predicate(name,jarity,module)) , TRUE ) && ( (*env)->ReleaseStringUTFChars(env,jname,name) , TRUE ) && ( jmodule != NULL ? ( (*env)->ReleaseStringUTFChars(env,jmodule,module), TRUE ) : TRUE ) && (rval=(*env)->AllocObject(env,jPredicateT_c)) != NULL && setPointerValue(env,rval,(pointer)predicate) ? ( DEBUG(1, Sdprintf("[predicate() module=%s\n",(module==NULL?"(null)":module))), rval ) : NULL // oughta warn of failure? ) ; } /* * Class: jpl_fli_PL * Method: predicate_info * Signature: (Ljpl/fli/predicate_t;Ljpl/fli/atom_t;ILjpl/fli/module_t;)I */ // // perhaps this oughta return a jboolean instead? // JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_predicate_1info( JNIEnv *env, jclass jProlog, jobject jpredicate, jobject jatom, // this Atom instance will have its value field destructively updated jobject jarity_holder, jobject jmodule ) { predicate_t predicate; atom_t atom; // update int arity; // update module_t module; // update return jpl_ensure_pvm_init(env) && jatom != NULL // must have an atom holder object && jarity_holder != NULL // must have an arity holder object && jmodule != NULL // must have a module holder object && getPointerValue(env,jpredicate,(pointer*)&predicate) // checks that jpredicate isn't null && ( PL_predicate_info(predicate,&atom,&arity,&module) , TRUE ) // "always succeeds"; returns void && updateAtomValue(env,jatom,atom) // unreg old ref, if any; reg new ref && setIntValue(env,jarity_holder,arity) // stash arity in holder && setPointerValue(env,jmodule,(pointer)module) // stash module ref in holder ; } //=== from "5.6.6 Calling Prolog from C: Initiating a query from C" =============================== /* * Class: jpl_fli_PL * Method: open_query * Signature: (Ljpl/fli/module_t;ILjpl/fli/predicate_t;Ljpl/fli/term_t;)Ljpl/fli/qid_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_open_1query( JNIEnv *env, jclass jProlog, jobject jmodule, // read jint jflags, // read jobject jpredicate, // read jobject jterm0 // read ) { module_t module; predicate_t predicate; term_t term0; qid_t qid; jobject jqid; // for returned new QidT object DEBUG(1, Sdprintf( ">open_query(env=%lu,jProlog=%lu,jmodule=%lu,jflags=%lu,jpredicate=%lu,jterm0=%lu)...\n", (long)env, (long)jProlog, (long)jmodule, (long)jflags, (long)jpredicate, (long)jterm0)); return ( jpl_ensure_pvm_init(env) && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // NULL module is OK below... && ( DEBUG(1, Sdprintf(" ok: getPointerValue(env,jmodule=%lu,&(pointer)module=%lu)\n",(long)jmodule,(long)module)), TRUE ) && getPointerValue(env,jpredicate,(pointer*)&predicate) // checks that jpredicate != NULL && ( DEBUG(1, Sdprintf(" ok: getPointerValue(env,jpredicate=%lu,&(pointer)predicate=%lu)\n",(long)jpredicate,(long)predicate)), TRUE ) && getLongValue(env,jterm0,(long*)&term0) // jterm0!=NULL && ( (qid=PL_open_query(module,jflags,predicate,term0)) , TRUE ) // NULL module is OK (?) [ISSUE] && ( DEBUG(1, Sdprintf(" ok: PL_open_query(module=%lu,jflags=%u,predicate=%lu,term0=%lu)=%lu\n",(long)module,jflags,(long)predicate,(long)term0,(long)qid)), TRUE ) && (jqid=(*env)->AllocObject(env,jQidT_c)) != NULL && ( DEBUG(1, Sdprintf(" ok: AllocObject(env,jQidT_c)=%lu\n",(long)jqid)), TRUE ) && setLongValue(env,jqid,(long)qid) && ( DEBUG(1, Sdprintf(" ok: setLongValue(env,%lu,%lu)\n",(long)jqid,(long)qid)), TRUE ) && ( DEBUG(1, Sdprintf("[open_query module = %s]\n", (module==NULL?"(null)":PL_atom_chars(PL_module_name(module))))), TRUE ) ? ( DEBUG(1, Sdprintf(" =%lu\n",(long)jqid)), jqid ) : NULL // oughta diagnose failure? raise JPL exception? ) ; } /* * Class: jpl_fli_PL * Method: next_solution * Signature: (Ljpl/fli/qid_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_next_1solution( JNIEnv *env, jclass jProlog, jobject jqid // read ) { qid_t qid; int rval; // for boolean return value DEBUG(1, Sdprintf( ">next_solution(env=%lu,jProlog=%lu,jqid=%lu)...\n", (long)env, (long)jProlog, (long)jqid)); return jpl_ensure_pvm_init(env) && getLongValue(env,jqid,(long*)&qid) // checks that jqid isn't null && ( DEBUG(1, Sdprintf( " ok: getLongValue(env,jqid,(long*)&qid(%lu))\n",(long)qid)), TRUE ) && ( rval=PL_next_solution(qid), TRUE ) // can call this until it returns FALSE && ( DEBUG(1, Sdprintf( " ok: PL_next_solution(qid=%lu)=%u\n",(long)qid,rval)), TRUE ) && ( DEBUG(1, Sdprintf(" =%lu\n",(long)rval)), rval ) ; } /* * Class: jpl_fli_PL * Method: cut_query * Signature: (Ljpl/fli/qid_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_cut_1query( JNIEnv *env, jclass jProlog, jobject jqid ) { qid_t qid; DEBUG(1, Sdprintf( ">cut_query(env=%lu,jProlog=%lu,jquid=%u)...\n", (long)env, (long)jProlog, (long)jqid)); if ( jpl_ensure_pvm_init(env) && getLongValue(env,jqid,(long*)&qid) // checks that jqid != NULL ) { PL_cut_query( qid); // void DEBUG(1, Sdprintf( " ok: PL_cut_query(%lu)\n", (long)qid)); } } /* * Class: jpl_fli_PL * Method: close_query * Signature: (Ljpl/fli/qid_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_close_1query( JNIEnv *env, jclass jProlog, jobject jqid ) { qid_t qid; DEBUG(1, Sdprintf( ">close_query(env=%lu,jProlog=%lu,jquid=%u)...\n", (long)env, (long)jProlog, (long)jqid)); if ( jpl_ensure_pvm_init(env) && getLongValue(env,jqid,(long*)&qid) // checks that jqid != NULL ) { PL_close_query( qid); // void DEBUG(1, Sdprintf( " ok: PL_close_query(%lu)\n", (long)qid)); } } /* * Class: jpl_fli_PL * Method: call_predicate * Signature: (Ljpl/fli/module_t;ILjpl/fli/predicate_t;Ljpl/fli/term_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_call_1predicate( JNIEnv *env, jclass jProlog, jobject jmodule, // null is OK jint jflags, jobject jpredicate, jobject jterm0 ) { module_t module; predicate_t predicate; term_t term0; return jpl_ensure_pvm_init(env) && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // if jmodule is null then module = NULL && getPointerValue(env,jpredicate,(pointer*)&predicate) // checks that jpredicate isn't null && getLongValue(env,jterm0,(long*)&term0) // checks that jterm0 isn't null && PL_call_predicate(module,jflags,predicate,term0) // assumes module == NULL is OK [ISSUE] ; } /* * Class: jpl_fli_PL * Method: call * Signature: (Ljpl/fli/term_t;Ljpl/fli/module_t;)Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_call( JNIEnv *env, jclass jProlog, jobject jterm, jobject jmodule // null is OK ) { term_t term; module_t module; return jpl_ensure_pvm_init(env) && getLongValue(env,jterm,(long*)&term) // checks that jterm != NULL && ( getPointerValue(env,jmodule,(pointer*)&module) , TRUE ) // if jmodule is null then module = NULL && PL_call(term,module) // assumes module == NULL is OK [ISSUE] ; } //=== from "5.6.9 Prolog exceptions in foreign code" ============================================== // not yet mapped: // raise_exception() // throw() /* * Class: jpl_fli_PL * Method: exception * Signature: (Ljpl/fli/qid_t;)Ljpl/fli/term_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_exception( JNIEnv *env, jclass jProlog, jobject jqid ) { qid_t qid; term_t term; jobject term_t; // return value DEBUG(1, Sdprintf( ">exception(jqid=%lu)\n", (long)jqid)); return ( jpl_ensure_pvm_init(env) && ( DEBUG(1, Sdprintf( " ok: jpl_ensure_pvm_init(env)\n")), TRUE ) // && jqid != NULL // redundant && ( DEBUG(1, Sdprintf( " ok: jqid != NULL\n")), TRUE ) && getLongValue(env,jqid,(long*)&qid) // checks that jqid isn't null && ( DEBUG(1, Sdprintf( " ok: getLongValue(env,jqid,(long*)&qid)\n")), TRUE ) && ( (term=PL_exception(qid)) , TRUE ) // we'll build a term_t object regardless && ( DEBUG(1, Spdrintf(" ok: ( (term=PL_exception(qid)), TRUE)\n")), TRUE ) && (term_t=(*env)->AllocObject(env,jTermT_c)) != NULL && ( DEBUG(1, Sdprintf( " ok: (term_t=(*env)->AllocObject(env,jTermT_c)) != NULL\n")), TRUE ) && setLongValue(env,term_t,(long)term) && ( DEBUG(1, Sdprintf( " ok: setLongValue(env,term_t,(long)term)\n")), TRUE ) ? ( DEBUG(1, Sdprintf(" =%lu\n",(long)term_t)), term_t ) : NULL // oughta diagnose failure? ) ; } //=== from "5.6.1 Miscellaneous" ================================================================== // not yet mapped (these might actually be useful as native methods, although they can be called via Prolog): // record() // reorded() // erase() /* * Class: jpl_fli_PL * Method: compare * Signature: (Ljpl/fli/term_t;Ljpl/fli/term_t;)I */ JNIEXPORT jint JNICALL // returns -1, 0 or 1 (or -2 for error) Java_jpl_fli_Prolog_compare( JNIEnv *env, jclass jProlog, jobject jterm1, jobject jterm2 ) { term_t term1; term_t term2; DEBUG(1, Sdprintf( ">compare(term1=%lu,term2=%lu)\n", (long)jterm1, (long)jterm2)); if ( jpl_ensure_pvm_init(env) && getLongValue(env,jterm1,(long*)&term1) // checks jterm1 isn't null && getLongValue(env,jterm2,(long*)&term2) // checks jterm2 isn't null ) { DEBUG(1, Sdprintf( "> PL_compare( %u, %u)", term1, term2)); return PL_compare(term1,term2); // returns -1, 0 or 1 } else { return -2; // oughta throw an exception... } } /* * Class: jpl_fli_PL * Method: unregister_atom * Signature: (Ljpl/fli/atom_t;)V */ JNIEXPORT void JNICALL Java_jpl_fli_Prolog_unregister_1atom( JNIEnv *env, jclass jProlog, jobject jatom ) { atom_t atom; DEBUG(1, Sdprintf( ">unregister_atom(env=%lu,jProlog=%lu,jatom=%u)...\n", (long)env, (long)jProlog, (long)jatom)); if ( jpl_ensure_pvm_init(env) && getLongValue(env,jatom,(long*)&atom) // checks that jatom isn't null ) { PL_unregister_atom( atom); // void DEBUG(1, Sdprintf( " ok: PL_unregister_atom(%lu)\n", (long)atom)); } } /* * Class: jpl_fli_PL * Method: new_module * Signature: (Ljpl/fli/atom_t;)Ljpl/fli/module_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_new_1module( JNIEnv *env, jclass jProlog, jobject jatom ) { atom_t atom; module_t module; jobject rval; return ( jpl_ensure_pvm_init(env) && getLongValue(env,jatom,(long*)&atom) // checks that jatom isn't null && ( (module=PL_new_module(atom)) , TRUE ) && (rval=(*env)->AllocObject(env,jModuleT_c)) != NULL && setPointerValue(env,rval,(pointer)module) ? rval : NULL // oughta warn of failure? ) ; } /* * Class: jpl_fli_PL * Method: action_abort * Signature: ()I */ JNIEXPORT int JNICALL Java_jpl_fli_Prolog_action_1abort( JNIEnv *env, jclass jProlog ) { if ( jpl_ensure_pvm_init(env) ) { return PL_action(PL_ACTION_ABORT); } else { return -2; // oughta throw exception? } } //=== JPL's Prolog engine pool and thread management =============================================== /* * Class: jpl_fli_PL * Method: thread_self * Signature: ()I */ JNIEXPORT jint JNICALL Java_jpl_fli_Prolog_thread_1self( JNIEnv *env, jclass jProlog ) { if ( jpl_ensure_pvm_init(env) ) { return PL_thread_self(); } else { return -2; } } static int create_pool_engines() { int i; DEBUG(1, Sdprintf( "JPL creating engine pool:\n")); if ( (engines=malloc(sizeof(PL_engine_t)*JPL_MAX_POOL_ENGINES)) == NULL ) { return -1; /* malloc failed */ } engines_allocated = JPL_MAX_POOL_ENGINES; memset(engines, 0, sizeof(PL_engine_t)*engines_allocated); DEBUG(1, Sdprintf( "JPL stashing default engine as [0]\n")); PL_set_engine( PL_ENGINE_CURRENT, &engines[0]); DEBUG(1, Sdprintf( "JPL detaching default engine\n")); // PL_set_engine( NULL, NULL); for ( i=1 ; iAllocObject(env,jEngineT_c)) != NULL && setPointerValue(env,rval,(pointer)engines[i]) ? rval : NULL ); } if ( rc != PL_ENGINE_INUSE ) { DEBUG(1, Sdprintf( "JPL PL_set_engine fails with %d\n", rc)); pthread_mutex_unlock( &engines_mutex); return NULL; // bad engine status: oughta throw exception } } for ( i=0 ; i 0 ) { DEBUG(1, Sdprintf("JPL releasing engine[%d]=%p\n", i, e)); PL_set_engine(NULL, NULL); pthread_cond_signal(&engines_cond); // alert waiters } return i; } else { return -2; } } /* * Class: jpl_fli_PL * Method: current_engine_is_pool * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_jpl_fli_Prolog_current_1engine_1is_1pool( JNIEnv *env, jclass jProlog ) { if ( jpl_ensure_pvm_init(env) ) { return current_pool_engine() >= 0; } else { return FALSE; // libpl could not be initialised: oughta throw exception } } /* * Class: jpl_fli_PL * Method: current_engine * Signature: ()Ljpl/fli/engine_t; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_current_1engine( JNIEnv *env, jclass jProlog ) { PL_engine_t engine; jobject rval; return ( jpl_ensure_pvm_init(env) && PL_thread_self() != -1 && ( current_pool_engine_handle(&engine) , TRUE ) && (rval=(*env)->AllocObject(env,jEngineT_c)) != NULL && setPointerValue(env,rval,(pointer)engine) ? rval : NULL ) ; } /* * Class: jpl_fli_PL * Method: get_c_lib_version * Signature: ()Ljava/lang/String; */ JNIEXPORT jobject JNICALL Java_jpl_fli_Prolog_get_1c_1lib_1version( JNIEnv *env, jclass jProlog ) { return (*env)->NewStringUTF(env,JPL_C_LIB_VERSION); } #ifdef _WIN32 #include int WINAPI PROTO(win_yap2swi, (HANDLE, DWORD, LPVOID)); int WINAPI win_yap2swi(HANDLE hinst, DWORD reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return 1; } #endif //=== end of jpl.c =================================================================================