#include "squirrel.h" #include "jni.h" #include #include #include #include "sqstdblobimpl.h" #include "dynamic_library.h" /*SquiLu local jni_functions = [ ["jint", "JNI_GetDefaultJavaVMInitArgs", "void *args"], ["jint", "JNI_CreateJavaVM", "JavaVM **pvm, void **penv, void *args"], ]; function write_jni_functions_declaration(){ foreach(k,v in jni_functions) { putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");"); putsnl("static " + v[1] + "_t dl_" + v[1] + " = 0;"); } } function write_jni_functions_load(){ foreach(k,v in jni_functions){ putsnl("dl_" + v[1] + " = (" + v[1] + "_t) libjni.dlsym(\"" + v[1] + "\");"); putsnl("if(!dl_" + v[1] + ") return false;"); } } SquiLu*/ static DynamicLibrary libjni; //@write_jni_functions_declaration(); // generated-code:begin typedef jint (*JNI_GetDefaultJavaVMInitArgs_t)(void *args); static JNI_GetDefaultJavaVMInitArgs_t dl_JNI_GetDefaultJavaVMInitArgs = 0; typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args); static JNI_CreateJavaVM_t dl_JNI_CreateJavaVM = 0; // generated-code:end static const SQChar *jvm_lib_name = #ifdef WIN32 _SC("jvm.dll"); #else _SC("/usr/lib/jvm/default-java/jre/lib/i386/client/libjvm.so"); #endif static bool load_libjni() { if(dl_JNI_CreateJavaVM) return true; if(libjni.open(jvm_lib_name)) { //@write_jni_functions_load(); // generated-code:begin dl_JNI_GetDefaultJavaVMInitArgs = (JNI_GetDefaultJavaVMInitArgs_t) libjni.dlsym("JNI_GetDefaultJavaVMInitArgs"); if(!dl_JNI_GetDefaultJavaVMInitArgs) return false; dl_JNI_CreateJavaVM = (JNI_CreateJavaVM_t) libjni.dlsym("JNI_CreateJavaVM"); if(!dl_JNI_CreateJavaVM) return false; // generated-code:end return true; } return false; } /* Java Type JNI Type machine dependent C/C++ typedef Signature Call...Method Get...Field boolean jboolean unsigned char Z Boolean byte jbyte signed char B Byte char jchar unsigned short C Char short jshort short S Short int jint int I Int long jlong long J Long float jfloat float F Float double jdouble double D Double void void V Void nonprimitive jobject *... L...; Object Examples method definition signature int m1 () ()I double m2 (long l, char c) (JC)D void m3 (String s, int[] a) (Ljava/lang/String;[I)V String m4 (boolean b) (Z)Ljava/lang/String; Object m4 (BigDecimal b) (Ljava/math/BigDecimal;)Ljava/lang/Object; */ #define JAVAVM_MAXOPTIONS 32 #define JAVAVM_JNIVERSION JNI_VERSION_1_6 static JavaVMOption _jvm_options[JAVAVM_MAXOPTIONS]; static JavaVM *_jvm_vm = 0; static JavaVMInitArgs _jvm_args; static JNIEnv *_jvm_env = 0; static const SQChar *Java_TAG = _SC("Java"); static SQRESULT check_jnienv(HSQUIRRELVM v){ if(!_jvm_env) return sq_throwerror(v, _SC("java vm is closed")); return SQ_OK; } #define CHECK_JNIENV() \ if((_rc_ = check_jnienv(v)) < 0) return _rc_; static const SQChar *JavaClass_TAG = _SC("_JavaClass_"); static const SQChar *_java_class_methods_key = _SC("_class_methods"); #define GET_java_class_INSTANCE_AT(idx) \ jclass self=NULL; \ if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)&self,(void*)JavaClass_TAG)) < 0) return _rc_; #define GET_java_class_INSTANCE() GET_java_class_INSTANCE_AT(1) static SQRESULT sq_java_class_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v) { jclass self = ((jclass)p); if (_jvm_env && self) _jvm_env->DeleteGlobalRef(self); return 0; } static SQRESULT sq_java_class_GetMethodID(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); CHECK_JNIENV(); GET_java_class_INSTANCE(); SQ_GET_STRING(v, 2, method_name); SQ_GET_STRING(v, 3, method_signature); jmethodID mid = _jvm_env->GetMethodID(self, method_name, method_signature); if(mid){ sq_pushstring(v, _java_class_methods_key, -1); if(sq_get(v, 1) == SQ_OK){ if(sq_gettype(v, -1) != OT_TABLE){ sq_poptop(v); sq_newtable(v); sq_pushstring(v, _java_class_methods_key, -1); sq_push(v, -2); sq_set(v, 1); } sq_push(v, 2); sq_pushuserpointer(v, mid); sq_set(v, -3); sq_pushbool(v, SQTrue); } else return sq_throwerror(v, _SC("instance field not found (%s)"), _java_class_methods_key); } else sq_pushbool(v, SQFalse); return 1; } static SQRESULT sq_java_class__get(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); CHECK_JNIENV(); GET_java_class_INSTANCE(); SQ_GET_STRING(v, 2, method_name); sq_pushbool(v, SQFalse); return 1; } static SQRESULT sq_java_class_currentTimeMillis(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); CHECK_JNIENV(); GET_java_class_INSTANCE(); jmethodID mid = _jvm_env->GetStaticMethodID(self, "currentTimeMillis", "()J"); if(mid){ jlong ms = _jvm_env->CallLongMethod(self, mid, NULL); sq_pushinteger(v, ms); } else sq_pushbool(v, SQFalse); return 1; } #define _DECL_FUNC(name,nparams,tycheck,isStatic) {_SC(#name), sq_java_class_##name,nparams,tycheck,isStatic} static SQRegFunction sq_java_class_methods[] = { _DECL_FUNC(GetMethodID, 3, _SC("xss"),SQFalse), _DECL_FUNC(_get, 2, _SC("xs"),SQFalse), _DECL_FUNC(currentTimeMillis, 1, _SC("x"),SQFalse), {0,0} }; #undef _DECL_FUNC static SQRESULT sq_java_open(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); if(_jvm_vm) return sq_throwerror(v, _SC("java vm already opened")); if(load_libjni()) { /* Create Java VM */ int num_options=0; _jvm_args.version = JAVAVM_JNIVERSION; dl_JNI_GetDefaultJavaVMInitArgs(&_jvm_args); _jvm_args.options = _jvm_options; _jvm_args.nOptions = num_options; _jvm_args.ignoreUnrecognized = JNI_TRUE; int res = dl_JNI_CreateJavaVM(&_jvm_vm, (void**) &_jvm_env, &_jvm_args); if (res < 0) return sq_throwerror(v, _SC("error creating Java VM: %d"), res); } else return sq_throwerror(v, _SC("Failed to load %s !"), jvm_lib_name); return 0; } static SQRESULT sq_java_close(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); CHECK_JNIENV(); _jvm_vm->DestroyJavaVM(); _jvm_vm = 0; _jvm_env = 0; return 0; } static SQRESULT sq_java_GetVersion(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); CHECK_JNIENV(); sq_pushinteger(v, _jvm_env->GetVersion()); return 1; } static SQRESULT sq_java_FindClass(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); CHECK_JNIENV(); SQ_GET_STRING(v, 2, klass); jclass cls = _jvm_env->FindClass(klass); if(cls){ cls = (jclass)_jvm_env->NewGlobalRef(cls); if(!cls) return sq_throwerror(v, _SC("JNI error: NewGlobalRef() failed")); sq_pushstring(v, JavaClass_TAG, -1); if(sq_getonroottable(v) == SQ_OK){ sq_createinstance(v, -1); sq_setinstanceup(v, -1, cls); sq_setreleasehook(v, -1, sq_java_class_releasehook); return 1; } } sq_pushnull(v); return 1; } #define _DECL_FUNC(name,nparams,tycheck,isStatic) {_SC(#name), sq_java_##name,nparams,tycheck,isStatic} static SQRegFunction sq_java_methods[] = { _DECL_FUNC(open, 1, _SC("y"),SQTrue), _DECL_FUNC(close, 1, _SC("y"),SQTrue), _DECL_FUNC(GetVersion, 1, _SC("y"),SQTrue), _DECL_FUNC(FindClass, 2, _SC("ys"),SQTrue), {0,0} }; #undef _DECL_FUNC #ifdef __cplusplus extern "C" { #endif SQRESULT sqext_register_Java(HSQUIRRELVM v) { sq_pushstring(v,Java_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(void*)Java_TAG); sq_insert_reg_funcs(v, sq_java_methods); sq_newslot(v,-3,SQTrue); sq_pushstring(v,JavaClass_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(void*)JavaClass_TAG); sq_insert_reg_funcs(v, sq_java_class_methods); sq_pushstring(v, _java_class_methods_key, -1); sq_pushnull(v); sq_newslot(v, -3, SQFalse); sq_newslot(v,-3,SQTrue); return 0; } #ifdef __cplusplus } #endif