sq_java.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #include "squirrel.h"
  2. #include "jni.h"
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include "sqstdblobimpl.h"
  7. #include "dynamic_library.h"
  8. /*SquiLu
  9. local jni_functions = [
  10. ["jint", "JNI_GetDefaultJavaVMInitArgs", "void *args"],
  11. ["jint", "JNI_CreateJavaVM", "JavaVM **pvm, void **penv, void *args"],
  12. ];
  13. function write_jni_functions_declaration(){
  14. foreach(k,v in jni_functions) {
  15. putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");");
  16. putsnl("static " + v[1] + "_t dl_" + v[1] + " = 0;");
  17. }
  18. }
  19. function write_jni_functions_load(){
  20. foreach(k,v in jni_functions){
  21. putsnl("dl_" + v[1] + " = (" + v[1] + "_t) libjni.dlsym(\"" + v[1] + "\");");
  22. putsnl("if(!dl_" + v[1] + ") return false;");
  23. }
  24. }
  25. SquiLu*/
  26. static DynamicLibrary libjni;
  27. //@write_jni_functions_declaration();
  28. // generated-code:begin
  29. typedef jint (*JNI_GetDefaultJavaVMInitArgs_t)(void *args);
  30. static JNI_GetDefaultJavaVMInitArgs_t dl_JNI_GetDefaultJavaVMInitArgs = 0;
  31. typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args);
  32. static JNI_CreateJavaVM_t dl_JNI_CreateJavaVM = 0;
  33. // generated-code:end
  34. static const SQChar *jvm_lib_name =
  35. #ifdef WIN32
  36. _SC("jvm.dll");
  37. #else
  38. _SC("/usr/lib/jvm/default-java/jre/lib/i386/client/libjvm.so");
  39. #endif
  40. static bool load_libjni()
  41. {
  42. if(dl_JNI_CreateJavaVM) return true;
  43. if(libjni.open(jvm_lib_name))
  44. {
  45. //@write_jni_functions_load();
  46. // generated-code:begin
  47. dl_JNI_GetDefaultJavaVMInitArgs = (JNI_GetDefaultJavaVMInitArgs_t) libjni.dlsym("JNI_GetDefaultJavaVMInitArgs");
  48. if(!dl_JNI_GetDefaultJavaVMInitArgs) return false;
  49. dl_JNI_CreateJavaVM = (JNI_CreateJavaVM_t) libjni.dlsym("JNI_CreateJavaVM");
  50. if(!dl_JNI_CreateJavaVM) return false;
  51. // generated-code:end
  52. return true;
  53. }
  54. return false;
  55. }
  56. /*
  57. Java Type JNI Type machine dependent
  58. C/C++ typedef Signature Call...Method
  59. Get...Field
  60. boolean jboolean unsigned char Z Boolean
  61. byte jbyte signed char B Byte
  62. char jchar unsigned short C Char
  63. short jshort short S Short
  64. int jint int I Int
  65. long jlong long J Long
  66. float jfloat float F Float
  67. double jdouble double D Double
  68. void void V Void
  69. nonprimitive jobject *... L...; Object
  70. Examples
  71. method definition signature
  72. int m1 () ()I
  73. double m2 (long l, char c) (JC)D
  74. void m3 (String s, int[] a) (Ljava/lang/String;[I)V
  75. String m4 (boolean b) (Z)Ljava/lang/String;
  76. Object m4 (BigDecimal b) (Ljava/math/BigDecimal;)Ljava/lang/Object;
  77. */
  78. #define JAVAVM_MAXOPTIONS 32
  79. #define JAVAVM_JNIVERSION JNI_VERSION_1_6
  80. static JavaVMOption _jvm_options[JAVAVM_MAXOPTIONS];
  81. static JavaVM *_jvm_vm = 0;
  82. static JavaVMInitArgs _jvm_args;
  83. static JNIEnv *_jvm_env = 0;
  84. static const SQChar *Java_TAG = _SC("Java");
  85. static SQRESULT check_jnienv(HSQUIRRELVM v){
  86. if(!_jvm_env) return sq_throwerror(v, _SC("java vm is closed"));
  87. return SQ_OK;
  88. }
  89. #define CHECK_JNIENV() \
  90. if((_rc_ = check_jnienv(v)) < 0) return _rc_;
  91. static const SQChar *JavaClass_TAG = _SC("_JavaClass_");
  92. static const SQChar *_java_class_methods_key = _SC("_class_methods");
  93. #define GET_java_class_INSTANCE_AT(idx) \
  94. jclass self=NULL; \
  95. if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)&self,(void*)JavaClass_TAG)) < 0) return _rc_;
  96. #define GET_java_class_INSTANCE() GET_java_class_INSTANCE_AT(1)
  97. static SQRESULT sq_java_class_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
  98. {
  99. jclass self = ((jclass)p);
  100. if (_jvm_env && self) _jvm_env->DeleteGlobalRef(self);
  101. return 0;
  102. }
  103. static SQRESULT sq_java_class_GetMethodID(HSQUIRRELVM v){
  104. SQ_FUNC_VARS_NO_TOP(v);
  105. CHECK_JNIENV();
  106. GET_java_class_INSTANCE();
  107. SQ_GET_STRING(v, 2, method_name);
  108. SQ_GET_STRING(v, 3, method_signature);
  109. jmethodID mid = _jvm_env->GetMethodID(self, method_name, method_signature);
  110. if(mid){
  111. sq_pushstring(v, _java_class_methods_key, -1);
  112. if(sq_get(v, 1) == SQ_OK){
  113. if(sq_gettype(v, -1) != OT_TABLE){
  114. sq_poptop(v);
  115. sq_newtable(v);
  116. sq_pushstring(v, _java_class_methods_key, -1);
  117. sq_push(v, -2);
  118. sq_set(v, 1);
  119. }
  120. sq_push(v, 2);
  121. sq_pushuserpointer(v, mid);
  122. sq_set(v, -3);
  123. sq_pushbool(v, SQTrue);
  124. }
  125. else return sq_throwerror(v, _SC("instance field not found (%s)"), _java_class_methods_key);
  126. }
  127. else sq_pushbool(v, SQFalse);
  128. return 1;
  129. }
  130. static SQRESULT sq_java_class__get(HSQUIRRELVM v){
  131. SQ_FUNC_VARS_NO_TOP(v);
  132. CHECK_JNIENV();
  133. GET_java_class_INSTANCE();
  134. SQ_GET_STRING(v, 2, method_name);
  135. sq_pushbool(v, SQFalse);
  136. return 1;
  137. }
  138. static SQRESULT sq_java_class_currentTimeMillis(HSQUIRRELVM v){
  139. SQ_FUNC_VARS_NO_TOP(v);
  140. CHECK_JNIENV();
  141. GET_java_class_INSTANCE();
  142. jmethodID mid = _jvm_env->GetStaticMethodID(self, "currentTimeMillis", "()J");
  143. if(mid){
  144. jlong ms = _jvm_env->CallLongMethod(self, mid, NULL);
  145. sq_pushinteger(v, ms);
  146. }
  147. else sq_pushbool(v, SQFalse);
  148. return 1;
  149. }
  150. #define _DECL_FUNC(name,nparams,tycheck,isStatic) {_SC(#name), sq_java_class_##name,nparams,tycheck,isStatic}
  151. static SQRegFunction sq_java_class_methods[] =
  152. {
  153. _DECL_FUNC(GetMethodID, 3, _SC("xss"),SQFalse),
  154. _DECL_FUNC(_get, 2, _SC("xs"),SQFalse),
  155. _DECL_FUNC(currentTimeMillis, 1, _SC("x"),SQFalse),
  156. {0,0}
  157. };
  158. #undef _DECL_FUNC
  159. static SQRESULT sq_java_open(HSQUIRRELVM v)
  160. {
  161. SQ_FUNC_VARS_NO_TOP(v);
  162. if(_jvm_vm) return sq_throwerror(v, _SC("java vm already opened"));
  163. if(load_libjni())
  164. {
  165. /* Create Java VM */
  166. int num_options=0;
  167. _jvm_args.version = JAVAVM_JNIVERSION;
  168. dl_JNI_GetDefaultJavaVMInitArgs(&_jvm_args);
  169. _jvm_args.options = _jvm_options;
  170. _jvm_args.nOptions = num_options;
  171. _jvm_args.ignoreUnrecognized = JNI_TRUE;
  172. int res = dl_JNI_CreateJavaVM(&_jvm_vm, (void**) &_jvm_env, &_jvm_args);
  173. if (res < 0) return sq_throwerror(v, _SC("error creating Java VM: %d"), res);
  174. }
  175. else return sq_throwerror(v, _SC("Failed to load %s !"), jvm_lib_name);
  176. return 0;
  177. }
  178. static SQRESULT sq_java_close(HSQUIRRELVM v){
  179. SQ_FUNC_VARS_NO_TOP(v);
  180. CHECK_JNIENV();
  181. _jvm_vm->DestroyJavaVM();
  182. _jvm_vm = 0;
  183. _jvm_env = 0;
  184. return 0;
  185. }
  186. static SQRESULT sq_java_GetVersion(HSQUIRRELVM v){
  187. SQ_FUNC_VARS_NO_TOP(v);
  188. CHECK_JNIENV();
  189. sq_pushinteger(v, _jvm_env->GetVersion());
  190. return 1;
  191. }
  192. static SQRESULT sq_java_FindClass(HSQUIRRELVM v){
  193. SQ_FUNC_VARS_NO_TOP(v);
  194. CHECK_JNIENV();
  195. SQ_GET_STRING(v, 2, klass);
  196. jclass cls = _jvm_env->FindClass(klass);
  197. if(cls){
  198. cls = (jclass)_jvm_env->NewGlobalRef(cls);
  199. if(!cls) return sq_throwerror(v, _SC("JNI error: NewGlobalRef() failed"));
  200. sq_pushstring(v, JavaClass_TAG, -1);
  201. if(sq_getonroottable(v) == SQ_OK){
  202. sq_createinstance(v, -1);
  203. sq_setinstanceup(v, -1, cls);
  204. sq_setreleasehook(v, -1, sq_java_class_releasehook);
  205. return 1;
  206. }
  207. }
  208. sq_pushnull(v);
  209. return 1;
  210. }
  211. #define _DECL_FUNC(name,nparams,tycheck,isStatic) {_SC(#name), sq_java_##name,nparams,tycheck,isStatic}
  212. static SQRegFunction sq_java_methods[] =
  213. {
  214. _DECL_FUNC(open, 1, _SC("y"),SQTrue),
  215. _DECL_FUNC(close, 1, _SC("y"),SQTrue),
  216. _DECL_FUNC(GetVersion, 1, _SC("y"),SQTrue),
  217. _DECL_FUNC(FindClass, 2, _SC("ys"),SQTrue),
  218. {0,0}
  219. };
  220. #undef _DECL_FUNC
  221. #ifdef __cplusplus
  222. extern "C" {
  223. #endif
  224. SQRESULT sqext_register_Java(HSQUIRRELVM v)
  225. {
  226. sq_pushstring(v,Java_TAG,-1);
  227. sq_newclass(v,SQFalse);
  228. sq_settypetag(v,-1,(void*)Java_TAG);
  229. sq_insert_reg_funcs(v, sq_java_methods);
  230. sq_newslot(v,-3,SQTrue);
  231. sq_pushstring(v,JavaClass_TAG,-1);
  232. sq_newclass(v,SQFalse);
  233. sq_settypetag(v,-1,(void*)JavaClass_TAG);
  234. sq_insert_reg_funcs(v, sq_java_class_methods);
  235. sq_pushstring(v, _java_class_methods_key, -1);
  236. sq_pushnull(v);
  237. sq_newslot(v, -3, SQFalse);
  238. sq_newslot(v,-3,SQTrue);
  239. return 0;
  240. }
  241. #ifdef __cplusplus
  242. }
  243. #endif