jni 0.2.3 → 0.3.0
raw patch · 5 files changed
+1024/−815 lines, 5 filesdep +choicedep ~inline-cnew-uploader
Dependencies added: choice
Dependency ranges changed: inline-c
Files
- jni.cabal +4/−2
- src/Foreign/JNI.c +110/−82
- src/Foreign/JNI.cpphs +839/−0
- src/Foreign/JNI.hs +0/−686
- src/Foreign/JNI/Types.hs +71/−45
jni.cabal view
@@ -1,5 +1,5 @@ name: jni-version: 0.2.3+version: 0.3.0 synopsis: Complete JNI raw bindings. description: Please see README.md. homepage: https://github.com/tweag/inline-java/tree/master/jni#readme@@ -34,8 +34,10 @@ build-depends: base >= 4.7 && < 5, bytestring >=0.10,+ choice >= 0.2.0, containers >=0.5,- inline-c >=0.5,+ inline-c >=0.5.6.1, singletons >= 2.0, thread-local-storage >=0.1+ build-tools: cpphs default-language: Haskell2010
src/Foreign/JNI.c view
@@ -20,12 +20,12 @@ } -JNIEnv * inline_c_Foreign_JNI_3_99b0dd0131b646dafcbe5e45017817ad4c5859cb() {+JNIEnv * inline_c_Foreign_JNI_3_7a31865bf33245c9e432165e1fe1577264708e3b() { jsize num_jvms; JavaVM *jvm;- -+ + JNI_GetCreatedJavaVMs(&jvm, 1, &num_jvms); JNIEnv *env; @@ -34,9 +34,9 @@ exit(EFAULT); } - --+ + + (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void**)&env, NULL); return env; }@@ -336,121 +336,149 @@ } -jobject inline_c_Foreign_JNI_53_8c39298123ed5c8656bc5277898eef8b54389907(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) {+void inline_c_Foreign_JNI_53_ace3bc46d6fd80627af710dce368567213addfaa(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject gobj_inline_c_2) {+ (*env_inline_c_0)->DeleteGlobalRef(env_inline_c_1+ ,gobj_inline_c_2);+ +}+++jobject inline_c_Foreign_JNI_54_16595ba5c6f78926bf8bd31d9d0e8bf072131bb0(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) { return (- (*env_inline_c_0)->NewGlobalRef(env_inline_c_1,- obj_inline_c_2) );+ (*env_inline_c_0)->NewGlobalRef(env_inline_c_1,+ obj_inline_c_2) ); } -void inline_c_Foreign_JNI_54_03477bcc772fad6c91dec2c4c759fcb4fc07724e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) {+jobject inline_c_Foreign_JNI_55_286b821e24496c30618bcd36d10e07939424a96e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) {+return (+ (*env_inline_c_0)->NewLocalRef(env_inline_c_1,+ obj_inline_c_2) );+} - (*env_inline_c_0)->DeleteGlobalRef(env_inline_c_1,- obj_inline_c_2); ++void inline_c_Foreign_JNI_56_f46c3362caa2b895c87351e1914a06c012eee294(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) {++ (*env_inline_c_0)->DeleteLocalRef(env_inline_c_1,+ obj_inline_c_2) ; } -void inline_c_Foreign_JNI_55_1fc0f64f3f314012d49ffbd906fd558d03aef37d(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {- (*env_inline_c_0)->CallVoidMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ;+jint inline_c_Foreign_JNI_57_c49bfdb1320e2f77592a15068a422089ae09feba(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jint capacity_inline_c_2) {++ (*env_inline_c_0)->PushLocalFrame(env_inline_c_1,+ capacity_inline_c_2); } -jobject inline_c_Foreign_JNI_56_203a086f6ff15893a2417732fde0904a88dd4307(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallObjectMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jobject inline_c_Foreign_JNI_58_53148f1b21d55375d63ea7ade9238bc4f16e149e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2) {+return (+ (*env_inline_c_0)->PopLocalFrame(env_inline_c_1,+ obj_inline_c_2) ); } -jboolean inline_c_Foreign_JNI_57_b729da20539bd62f9d8b8e8579dbf42bbafc76c4(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallBooleanMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+void inline_c_Foreign_JNI_59_8d66436d754c77c4f92234fe2c72cb9e8a9ad940(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+ (*env_inline_c_0)->CallVoidMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ; } -jbyte inline_c_Foreign_JNI_58_4e4bdbfc154de6ffe6eb562e1edfcbb529c275e8(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallByteMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jobject inline_c_Foreign_JNI_60_15d6a4ae1fac1a6ba84db740b2bfac9d44b23329(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallObjectMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jchar inline_c_Foreign_JNI_59_5e000da030371e4db09c808934e3e5f504eda6c9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallCharMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jboolean inline_c_Foreign_JNI_61_71e1f15d31cfe83371d148dbf20d2aebf0293c53(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallBooleanMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jshort inline_c_Foreign_JNI_60_516aded3c2f638c87a12e56d246bdcea1c7e1a47(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallShortMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jbyte inline_c_Foreign_JNI_62_5c031f42ce827bc7ef3320331f4333dfb7ddaa3a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallByteMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jint inline_c_Foreign_JNI_61_58b123994733ee132cc23af0e5a7da34ef37f584(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallIntMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jchar inline_c_Foreign_JNI_63_f67cb9064f7392b8f942ac21b300b8594ddc8043(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallCharMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jlong inline_c_Foreign_JNI_62_46357804ee4af723721f601341c61ac4eecad475(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallLongMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jshort inline_c_Foreign_JNI_64_3dc48e937e27459da9000a1fba7694c91562fbd6(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallShortMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jfloat inline_c_Foreign_JNI_63_75b26f9688a40ee63e314f73ee5f9563c48e02c0(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallFloatMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jint inline_c_Foreign_JNI_65_0d9906f84552f67ba8fc08d4403ca6919417f4de(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallIntMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jdouble inline_c_Foreign_JNI_64_f33654d183f21d1a2c8ffc121684d4e60e273fa2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {-return ( (*env_inline_c_0)->CallDoubleMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+jlong inline_c_Foreign_JNI_66_ff3b913f1c1e13665522e2fa9f46cf345cef625e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallLongMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -void inline_c_Foreign_JNI_65_5e76a5cd24826d8a13100c53ae77823083465978(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jfloat inline_c_Foreign_JNI_67_7d9a7c851ecb7d144f8aadac5cb17df79f87edfc(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallFloatMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+}+++jdouble inline_c_Foreign_JNI_68_9928358856d291d7c670b6bb00810c66255dcc65(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject obj_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+return ( (*env_inline_c_0)->CallDoubleMethodA(env_inline_c_1, obj_inline_c_2, method_inline_c_3, cargs_inline_c_4) );+}+++void inline_c_Foreign_JNI_69_5e76a5cd24826d8a13100c53ae77823083465978(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { (*env_inline_c_0)->CallStaticVoidMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ; } -jobject inline_c_Foreign_JNI_66_6b65c20aae594d93c02434b3de002e443794ad14(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jobject inline_c_Foreign_JNI_70_6b65c20aae594d93c02434b3de002e443794ad14(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticObjectMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jboolean inline_c_Foreign_JNI_67_58bcbcce6c8bf92799bd1db44c288a7b0a260a36(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jboolean inline_c_Foreign_JNI_71_58bcbcce6c8bf92799bd1db44c288a7b0a260a36(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticBooleanMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jbyte inline_c_Foreign_JNI_68_1f0c41a419f29557514552df4d07022a006f2ca3(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jbyte inline_c_Foreign_JNI_72_1f0c41a419f29557514552df4d07022a006f2ca3(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticByteMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jchar inline_c_Foreign_JNI_69_51a3cb1cefc6391ba5958a887d84196690a418f2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jchar inline_c_Foreign_JNI_73_51a3cb1cefc6391ba5958a887d84196690a418f2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticCharMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jshort inline_c_Foreign_JNI_70_5822dfce2b301e3b90f80885a4a5838bdc57cd44(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jshort inline_c_Foreign_JNI_74_5822dfce2b301e3b90f80885a4a5838bdc57cd44(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticShortMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jint inline_c_Foreign_JNI_71_4fdc28424fe7ef156763f715ef79463ed387abb2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jint inline_c_Foreign_JNI_75_4fdc28424fe7ef156763f715ef79463ed387abb2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticIntMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jlong inline_c_Foreign_JNI_72_93382b358dc7f0275c6a620eaa67fdfd75167d54(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jlong inline_c_Foreign_JNI_76_93382b358dc7f0275c6a620eaa67fdfd75167d54(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticLongMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jfloat inline_c_Foreign_JNI_73_89ea2435847f3d94e8b71bcceba739a077829ca9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jfloat inline_c_Foreign_JNI_77_89ea2435847f3d94e8b71bcceba739a077829ca9(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticFloatMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jdouble inline_c_Foreign_JNI_74_0b9bb41f21f19495338507ff5779f50a17ac0245(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) {+jdouble inline_c_Foreign_JNI_78_0b9bb41f21f19495338507ff5779f50a17ac0245(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jclass cls_inline_c_2, jmethodID method_inline_c_3, jvalue * cargs_inline_c_4) { return ( (*env_inline_c_0)->CallStaticDoubleMethodA(env_inline_c_1, cls_inline_c_2, method_inline_c_3, cargs_inline_c_4) ); } -jobjectArray inline_c_Foreign_JNI_75_0b57533e83360b5a6660bf703521b3b6c2fbec66(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2, jclass cls_inline_c_3) {+jobjectArray inline_c_Foreign_JNI_79_0b57533e83360b5a6660bf703521b3b6c2fbec66(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2, jclass cls_inline_c_3) { return ( (*env_inline_c_0)->NewObjectArray(env_inline_c_1, sz_inline_c_2,@@ -459,47 +487,47 @@ } -jbooleanArray inline_c_Foreign_JNI_76_b1841567b8f0e99405458b9e8a3b7f3a3e20812f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jbooleanArray inline_c_Foreign_JNI_80_b1841567b8f0e99405458b9e8a3b7f3a3e20812f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewBooleanArray(env_inline_c_1, sz_inline_c_2) ); } -jbyteArray inline_c_Foreign_JNI_77_1a9345ff427557126ba3aa5f0fb460f3df632ff8(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jbyteArray inline_c_Foreign_JNI_81_1a9345ff427557126ba3aa5f0fb460f3df632ff8(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewByteArray(env_inline_c_1, sz_inline_c_2) ); } -jcharArray inline_c_Foreign_JNI_78_b00869a9422815fdc3aa43f15e3b782dc6f19e03(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jcharArray inline_c_Foreign_JNI_82_b00869a9422815fdc3aa43f15e3b782dc6f19e03(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewCharArray(env_inline_c_1, sz_inline_c_2) ); } -jshortArray inline_c_Foreign_JNI_79_06a1e38de0ed2d7764757388457ed0797c72d8aa(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jshortArray inline_c_Foreign_JNI_83_06a1e38de0ed2d7764757388457ed0797c72d8aa(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewShortArray(env_inline_c_1, sz_inline_c_2) ); } -jintArray inline_c_Foreign_JNI_80_af7c087746afd64be9d977ebf078c2df4b3d918e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jintArray inline_c_Foreign_JNI_84_af7c087746afd64be9d977ebf078c2df4b3d918e(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewIntArray(env_inline_c_1, sz_inline_c_2) ); } -jlongArray inline_c_Foreign_JNI_81_270c75c62cc97fdc3741af544fa35a61abf37fba(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jlongArray inline_c_Foreign_JNI_85_270c75c62cc97fdc3741af544fa35a61abf37fba(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewLongArray(env_inline_c_1, sz_inline_c_2) ); } -jfloatArray inline_c_Foreign_JNI_82_312dee8af1c4b2058cb1b2703277cf297ba34224(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jfloatArray inline_c_Foreign_JNI_86_312dee8af1c4b2058cb1b2703277cf297ba34224(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewFloatArray(env_inline_c_1, sz_inline_c_2) ); } -jdoubleArray inline_c_Foreign_JNI_83_103070e78986a21762e18c9aebfa9162a3565d9b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) {+jdoubleArray inline_c_Foreign_JNI_87_103070e78986a21762e18c9aebfa9162a3565d9b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jsize sz_inline_c_2) { return ( (*env_inline_c_0)->NewDoubleArray(env_inline_c_1, sz_inline_c_2) ); } -jstring inline_c_Foreign_JNI_84_d5ed5b314231e7dc3292c2329a2cb4191e262633(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jchar * ptr_inline_c_2, jsize len_inline_c_3) {+jstring inline_c_Foreign_JNI_88_d5ed5b314231e7dc3292c2329a2cb4191e262633(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jchar * ptr_inline_c_2, jsize len_inline_c_3) { return ( (*env_inline_c_0)->NewString(env_inline_c_1, ptr_inline_c_2,@@ -507,61 +535,61 @@ } -jsize inline_c_Foreign_JNI_85_9be0134c89fa74c4d07a2601d81d89982ce8bdf6(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2) {+jsize inline_c_Foreign_JNI_89_9be0134c89fa74c4d07a2601d81d89982ce8bdf6(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2) { return ( (*env_inline_c_0)->GetArrayLength(env_inline_c_1, array_inline_c_2) ); } -jsize inline_c_Foreign_JNI_86_2e55ce4ded52c43b7b69c0c49c4425aef4f8a80b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) {+jsize inline_c_Foreign_JNI_90_2e55ce4ded52c43b7b69c0c49c4425aef4f8a80b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) { return ( (*env_inline_c_0)->GetStringLength(env_inline_c_1, jstr_inline_c_2) ); } -jboolean * inline_c_Foreign_JNI_87_153a97a3a91d03dbe7d10fe0e3d48afaa842ee96(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jboolean * inline_c_Foreign_JNI_91_153a97a3a91d03dbe7d10fe0e3d48afaa842ee96(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetBooleanArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -jbyte * inline_c_Foreign_JNI_88_b630cdc25e3d575cad69a3fc3bec490a99a6ab49(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jbyte * inline_c_Foreign_JNI_92_b630cdc25e3d575cad69a3fc3bec490a99a6ab49(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetByteArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -jchar * inline_c_Foreign_JNI_89_7c0f806fe4d40ac0c1d06b4ccccc42fdc562c8ec(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jchar * inline_c_Foreign_JNI_93_7c0f806fe4d40ac0c1d06b4ccccc42fdc562c8ec(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetCharArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -jshort * inline_c_Foreign_JNI_90_66e42eb3b8a0e71cc0cc2b722b925689a20ed23f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jshort * inline_c_Foreign_JNI_94_66e42eb3b8a0e71cc0cc2b722b925689a20ed23f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetShortArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -jint * inline_c_Foreign_JNI_91_9ca3666fbed332c3a833881ceba71295e27d5d16(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jint * inline_c_Foreign_JNI_95_9ca3666fbed332c3a833881ceba71295e27d5d16(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetIntArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -jlong * inline_c_Foreign_JNI_92_3bd0969839fbd68b98c00a27f6197704f6e2718b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jlong * inline_c_Foreign_JNI_96_3bd0969839fbd68b98c00a27f6197704f6e2718b(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetLongArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -jfloat * inline_c_Foreign_JNI_93_1799b6e92e7df6d5155518d25fe2fde47055a7ff(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jfloat * inline_c_Foreign_JNI_97_1799b6e92e7df6d5155518d25fe2fde47055a7ff(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetFloatArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -jdouble * inline_c_Foreign_JNI_94_6b454504f66bff257e7cb14d00f7064112a8f5a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) {+jdouble * inline_c_Foreign_JNI_98_6b454504f66bff257e7cb14d00f7064112a8f5a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2) { return ( (*env_inline_c_0)->GetDoubleArrayElements(env_inline_c_1, array_inline_c_2, NULL) ); } -const jchar * inline_c_Foreign_JNI_95_ac075a3bdcb535575fe36c6f7b5eb3d66ace44a7(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) {+const jchar * inline_c_Foreign_JNI_99_ac075a3bdcb535575fe36c6f7b5eb3d66ace44a7(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2) { return ( (*env_inline_c_0)->GetStringChars(env_inline_c_1, jstr_inline_c_2,@@ -569,87 +597,87 @@ } -void inline_c_Foreign_JNI_96_c405fd2cc3cc77bea5093b022f17d3b2c443e2a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbooleanArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jboolean * buf_inline_c_5) {+void inline_c_Foreign_JNI_100_c405fd2cc3cc77bea5093b022f17d3b2c443e2a2(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbooleanArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jboolean * buf_inline_c_5) { (*env_inline_c_0)->SetBooleanArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_97_6aefb6e6ad5f3a169ff39bd2c3186b897bcd220f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbyteArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jbyte * buf_inline_c_5) {+void inline_c_Foreign_JNI_101_6aefb6e6ad5f3a169ff39bd2c3186b897bcd220f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jbyteArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jbyte * buf_inline_c_5) { (*env_inline_c_0)->SetByteArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_98_a1e161a18fa39331bad743b7e07b0399b3104242(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jcharArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jchar * buf_inline_c_5) {+void inline_c_Foreign_JNI_102_a1e161a18fa39331bad743b7e07b0399b3104242(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jcharArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jchar * buf_inline_c_5) { (*env_inline_c_0)->SetCharArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_99_4221edb9c7b0c1666f5952fe23aad965e2f58085(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jshortArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jshort * buf_inline_c_5) {+void inline_c_Foreign_JNI_103_4221edb9c7b0c1666f5952fe23aad965e2f58085(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jshortArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jshort * buf_inline_c_5) { (*env_inline_c_0)->SetShortArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_100_0cf86cc89e108bd7ed150e5aad2e7d8d8f95dd7a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jintArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jint * buf_inline_c_5) {+void inline_c_Foreign_JNI_104_0cf86cc89e108bd7ed150e5aad2e7d8d8f95dd7a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jintArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jint * buf_inline_c_5) { (*env_inline_c_0)->SetIntArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_101_983cb43fd1962ef866086f1819815a8b05791888(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jlongArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jlong * buf_inline_c_5) {+void inline_c_Foreign_JNI_105_983cb43fd1962ef866086f1819815a8b05791888(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jlongArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jlong * buf_inline_c_5) { (*env_inline_c_0)->SetLongArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_102_26c6b32031e2561eb5fc3b047d493c3a784bbf40(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jfloatArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jfloat * buf_inline_c_5) {+void inline_c_Foreign_JNI_106_26c6b32031e2561eb5fc3b047d493c3a784bbf40(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jfloatArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jfloat * buf_inline_c_5) { (*env_inline_c_0)->SetFloatArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_103_fbded71aa93cca94c495be618b75c7f610619a93(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jdoubleArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jdouble * buf_inline_c_5) {+void inline_c_Foreign_JNI_107_fbded71aa93cca94c495be618b75c7f610619a93(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jdoubleArray array_inline_c_2, jsize start_inline_c_3, jsize len_inline_c_4, jdouble * buf_inline_c_5) { (*env_inline_c_0)->SetDoubleArrayRegion(env_inline_c_1, array_inline_c_2, start_inline_c_3, len_inline_c_4, buf_inline_c_5) ; } -void inline_c_Foreign_JNI_104_5d5355f911ff38accf7df59e4f3407823efa0055(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jboolean * xs_inline_c_3) {+void inline_c_Foreign_JNI_108_5d5355f911ff38accf7df59e4f3407823efa0055(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jboolean * xs_inline_c_3) { (*env_inline_c_0)->ReleaseBooleanArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_105_93701f28f0a45b8531f977f3ad28d48b747bb58c(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jbyte * xs_inline_c_3) {+void inline_c_Foreign_JNI_109_93701f28f0a45b8531f977f3ad28d48b747bb58c(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jbyte * xs_inline_c_3) { (*env_inline_c_0)->ReleaseByteArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_106_d799968701da7f57e4eb07390e1efda373184222(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jchar * xs_inline_c_3) {+void inline_c_Foreign_JNI_110_d799968701da7f57e4eb07390e1efda373184222(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jchar * xs_inline_c_3) { (*env_inline_c_0)->ReleaseCharArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_107_03e0c5a40ab324b1c42f0b70ceaeb6b1605a0ded(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jshort * xs_inline_c_3) {+void inline_c_Foreign_JNI_111_03e0c5a40ab324b1c42f0b70ceaeb6b1605a0ded(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jshort * xs_inline_c_3) { (*env_inline_c_0)->ReleaseShortArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_108_4c2726a53e147cd6eb61733e27bfc599bc883f74(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jint * xs_inline_c_3) {+void inline_c_Foreign_JNI_112_4c2726a53e147cd6eb61733e27bfc599bc883f74(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jint * xs_inline_c_3) { (*env_inline_c_0)->ReleaseIntArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_109_9e1790871e959852cb5032b3f2833c370b81bb0f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jlong * xs_inline_c_3) {+void inline_c_Foreign_JNI_113_9e1790871e959852cb5032b3f2833c370b81bb0f(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jlong * xs_inline_c_3) { (*env_inline_c_0)->ReleaseLongArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_110_44c06b418c79983d60f09ffc49851077b1feb632(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jfloat * xs_inline_c_3) {+void inline_c_Foreign_JNI_114_44c06b418c79983d60f09ffc49851077b1feb632(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jfloat * xs_inline_c_3) { (*env_inline_c_0)->ReleaseFloatArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_111_94830601ce91790b75e74abe9c9819be2e748762(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jdouble * xs_inline_c_3) {+void inline_c_Foreign_JNI_115_94830601ce91790b75e74abe9c9819be2e748762(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobject array_inline_c_2, jdouble * xs_inline_c_3) { (*env_inline_c_0)->ReleaseDoubleArrayElements(env_inline_c_1, array_inline_c_2, xs_inline_c_3, JNI_ABORT) ; } -void inline_c_Foreign_JNI_112_7a962d5f8e6114066dca42386535e4a079022eae(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2, jchar * chars_inline_c_3) {+void inline_c_Foreign_JNI_116_7a962d5f8e6114066dca42386535e4a079022eae(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jstring jstr_inline_c_2, jchar * chars_inline_c_3) { (*env_inline_c_0)->ReleaseStringChars(env_inline_c_1, jstr_inline_c_2,@@ -657,7 +685,7 @@ } -jobject inline_c_Foreign_JNI_113_bb66272284cce01d85b6ec31967e1a66eae7e0c5(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2, jsize i_inline_c_3) {+jobject inline_c_Foreign_JNI_117_bb66272284cce01d85b6ec31967e1a66eae7e0c5(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jarray array_inline_c_2, jsize i_inline_c_3) { return ( (*env_inline_c_0)->GetObjectArrayElement(env_inline_c_1, array_inline_c_2,@@ -665,7 +693,7 @@ } -void inline_c_Foreign_JNI_114_c069b4edd080791f4858d4a7a48b8c42c99c8e4a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobjectArray array_inline_c_2, jsize i_inline_c_3, jobject x_inline_c_4) {+void inline_c_Foreign_JNI_118_c069b4edd080791f4858d4a7a48b8c42c99c8e4a(JNIEnv * env_inline_c_0, JNIEnv * env_inline_c_1, jobjectArray array_inline_c_2, jsize i_inline_c_3, jobject x_inline_c_4) { (*env_inline_c_0)->SetObjectArrayElement(env_inline_c_1, array_inline_c_2,
+ src/Foreign/JNI.cpphs view
@@ -0,0 +1,839 @@+-- | Low-level bindings to the Java Native Interface (JNI).+--+-- Read the+-- <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html JNI spec>+-- for authoritative documentation as to what each of the functions in+-- this module does. The names of the bindings in this module were chosen to+-- match the names of the functions in the JNI spec.+--+-- All bindings in this module access the JNI via a thread-local variable of+-- type @JNIEnv *@. If the current OS thread has not yet been "attached" to the+-- JVM, it is attached implicitly upon the first call to one of these bindings+-- in the current thread.+--+-- The 'String' type in this module is the type of JNI strings. See+-- "Foreign.JNI.String".++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedLabels #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-}++-- XXX pgmP directive should be redundant. But necessary to workaround+-- https://github.com/haskell/cabal/issues/4278.+{-# OPTIONS_GHC -fno-warn-name-shadowing -pgmPcpphs -optP--cpp #-}++-- XXX This file uses cpphs for preprocessing instead of the system's native+-- CPP, because the OS X has subtly different whitespace behaviour in the+-- presence of concatenation.++module Foreign.JNI+ ( -- * JNI functions+ -- ** VM creation+ withJVM+ -- ** Class loading+ , defineClass+ , JNINativeMethod(..)+ , registerNatives+ -- ** Exceptions+ , JVMException(..)+ , throw+ , throwNew+ -- ** Query functions+ , findClass+ , getFieldID+ , getStaticFieldID+ , getMethodID+ , getStaticMethodID+ , getObjectClass+ -- ** Reference manipulation+ , newGlobalRef+ , deleteGlobalRef+ , newLocalRef+ , deleteLocalRef+ , pushLocalFrame+ , popLocalFrame+ -- ** Field accessor functions+ -- *** Get fields+ , getObjectField+ , getBooleanField+ , getIntField+ , getLongField+ , getCharField+ , getShortField+ , getByteField+ , getDoubleField+ , getFloatField+ -- *** Get static fields+ , getStaticObjectField+ , getStaticBooleanField+ , getStaticIntField+ , getStaticLongField+ , getStaticCharField+ , getStaticShortField+ , getStaticByteField+ , getStaticDoubleField+ , getStaticFloatField+ -- *** Set fields+ , setObjectField+ , setBooleanField+ , setIntField+ , setLongField+ , setCharField+ , setShortField+ , setByteField+ , setDoubleField+ , setFloatField+ -- *** Set static fields+ , setStaticObjectField+ , setStaticBooleanField+ , setStaticIntField+ , setStaticLongField+ , setStaticCharField+ , setStaticShortField+ , setStaticByteField+ , setStaticDoubleField+ , setStaticFloatField+ -- ** Method invocation+ , callObjectMethod+ , callBooleanMethod+ , callIntMethod+ , callLongMethod+ , callCharMethod+ , callShortMethod+ , callByteMethod+ , callDoubleMethod+ , callFloatMethod+ , callVoidMethod+ , callStaticObjectMethod+ , callStaticVoidMethod+ , callStaticBooleanMethod+ , callStaticIntMethod+ , callStaticLongMethod+ , callStaticCharMethod+ , callStaticShortMethod+ , callStaticByteMethod+ , callStaticDoubleMethod+ , callStaticFloatMethod+ -- ** Object construction+ , newObject+ , newString+ , newObjectArray+ , newBooleanArray+ , newByteArray+ , newCharArray+ , newShortArray+ , newIntArray+ , newLongArray+ , newFloatArray+ , newDoubleArray+ -- ** Array manipulation+ , getArrayLength+ , getStringLength+ , ArrayCopyFailed(..)+ , getBooleanArrayElements+ , getByteArrayElements+ , getCharArrayElements+ , getShortArrayElements+ , getIntArrayElements+ , getLongArrayElements+ , getFloatArrayElements+ , getDoubleArrayElements+ , getStringChars+ , setBooleanArrayRegion+ , setByteArrayRegion+ , setCharArrayRegion+ , setShortArrayRegion+ , setIntArrayRegion+ , setLongArrayRegion+ , setFloatArrayRegion+ , setDoubleArrayRegion+ , releaseBooleanArrayElements+ , releaseByteArrayElements+ , releaseCharArrayElements+ , releaseShortArrayElements+ , releaseIntArrayElements+ , releaseLongArrayElements+ , releaseFloatArrayElements+ , releaseDoubleArrayElements+ , releaseStringChars+ , getObjectArrayElement+ , setObjectArrayElement+ ) where++import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, takeMVar)+import Control.Exception (Exception, bracket, finally, throwIO)+import Control.Monad (join, unless, void, when)+import Data.Choice+import Data.Coerce+import Data.Int+import Data.IORef (IORef, newIORef, readIORef, atomicModifyIORef)+import Data.Word+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.Monoid ((<>))+import Data.Typeable (Typeable)+import Data.TLS.PThread+import Foreign.C (CChar)+import Foreign.ForeignPtr+ ( finalizeForeignPtr+ , newForeignPtr_+ , withForeignPtr+ )+import Foreign.JNI.NativeMethod+import Foreign.JNI.Types+import qualified Foreign.JNI.String as JNI+import Foreign.Marshal.Array+import Foreign.Ptr (Ptr, nullPtr)+import GHC.ForeignPtr (newConcForeignPtr)+import qualified Language.C.Inline as C+import qualified Language.C.Inline.Unsafe as CU+import System.IO.Unsafe (unsafePerformIO)+import Prelude hiding (String)++C.context (C.baseCtx <> C.bsCtx <> jniCtx)++C.include "<jni.h>"+C.include "<errno.h>"+C.include "<stdlib.h>"++-- | A JNI call may cause a (Java) exception to be raised. This module raises it+-- as a Haskell exception wrapping the Java exception.+newtype JVMException = JVMException JThrowable+ deriving (Show, Typeable)++instance Exception JVMException++-- | Thrown when @Get<PrimitiveType>ArrayElements@ returns a null pointer,+-- because it wanted to copy the array contents but couldn't. In this case the+-- JVM doesn't throw OutOfMemory according to the JNI spec.+data ArrayCopyFailed = ArrayCopyFailed+ deriving (Show, Typeable)++instance Exception ArrayCopyFailed++objectFromPtr :: Ptr (J a) -> IO (J a)+objectFromPtr ptr = J <$> newForeignPtr_ ptr++-- | Map Java exceptions to Haskell exceptions.+throwIfException :: Ptr JNIEnv -> IO a -> IO a+throwIfException env m = m `finally` do+ excptr <- [CU.exp| jthrowable { (*$(JNIEnv *env))->ExceptionOccurred($(JNIEnv *env)) } |]+ unless (excptr == nullPtr) $ do+ [CU.exp| void { (*$(JNIEnv *env))->ExceptionDescribe($(JNIEnv *env)) } |]+ [CU.exp| void { (*$(JNIEnv *env))->ExceptionClear($(JNIEnv *env)) } |]+ throwIO . JVMException =<< newGlobalRef =<< objectFromPtr excptr++-- | Check whether a pointer is null.+throwIfNull :: IO (Ptr a) -> IO (Ptr a)+throwIfNull m = do+ ptr <- m+ if ptr == nullPtr+ then throwIO ArrayCopyFailed+ else return ptr++-- | A read-write lock+--+-- Concurrent readers are allowed, but only one writer is supported.+newtype RWLock =+ RWLock (IORef (Int, RWWantedState))+ -- ^ A count of the held read locks and the wanted state++-- | The wanted state of the RW+data RWWantedState+ = Reading -- ^ There are no writers+ | Writing (MVar ())+ -- ^ A writer wants to write, grant no more read locks. The MVar is used+ -- to notify the writer when the currently held read locks are released.++-- | Creates a new read-write lock.+newRWLock :: IO RWLock+newRWLock = RWLock <$> newIORef (0, Reading)++-- | Tries to acquire a read lock. If this call returns `Do #read`, no writer+-- will be granted a lock before the read lock is released.+tryAcquireReadLock :: RWLock -> IO (Choice "read")+tryAcquireReadLock (RWLock ref) = do+ atomicModifyIORef ref $ \case+ (!readers, Reading) -> ((readers + 1, Reading), Do #read)+ st -> ( st, Don't #read)++-- | Releases a read lock.+releaseReadLock :: RWLock -> IO ()+releaseReadLock (RWLock ref) = do+ st <- atomicModifyIORef ref $+ \st@(readers, aim) -> ((readers - 1, aim), st)+ case st of+ -- Notify the writer if I'm the last reader.+ (0, Writing mv) -> putMVar mv ()+ _ -> return ()++-- | Waits until the current read locks are released and grants a write lock.+acquireWriteLock :: RWLock -> IO ()+acquireWriteLock (RWLock ref) = do+ mv <- newEmptyMVar+ join $ atomicModifyIORef ref $ \case+ (0, _) -> ((0, Writing mv), return ())+ st -> ( st, takeMVar mv)++-- | This lock is used to avoid the JVM from dying before any finalizers+-- deleting global references are finished.+--+-- Finalizers try to acquire read locks.+--+-- The JVM acquires a write lock before shutdown. Thence, finalizers fail to+-- acquire read locks and behave as noops.+globalJVMLock :: RWLock+globalJVMLock = unsafePerformIO newRWLock+{-# NOINLINE globalJVMLock #-}++-- | A global mutable cell holding the TLS variable, whose content is set once+-- for each thread.+envTlsRef :: IORef (TLS (Ptr JNIEnv))+{-# NOINLINE envTlsRef #-}+envTlsRef = unsafePerformIO $ do+ -- It doesn't matter if this computation ends up running twice, say because+ -- of lazy blackholing.+ !tls <- mkTLS $ [C.block| JNIEnv* {+ jsize num_jvms;+ JavaVM *jvm;+ /* Assume there's at most one JVM. The current JNI spec (2016) says only+ * one JVM per process is supported anyways. */+ JNI_GetCreatedJavaVMs(&jvm, 1, &num_jvms);+ JNIEnv *env;++ if(!num_jvms) {+ fprintf(stderr, "No JVM has been initialized yet.\n");+ exit(EFAULT);+ }++ /* Attach as daemon to match GHC's usual semantics for threads, which are+ * daemonic.+ */+ (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void**)&env, NULL);+ return env; } |]+ newIORef tls++-- | Run an action against the appropriate 'JNIEnv'.+--+-- Each OS thread has its own 'JNIEnv', which this function gives access to.+--+-- TODO check whether this call is only safe from a (bound) thread.+withJNIEnv :: (Ptr JNIEnv -> IO a) -> IO a+withJNIEnv f = f =<< getTLS =<< readIORef envTlsRef++useAsCStrings :: [ByteString] -> ([Ptr CChar] -> IO a) -> IO a+useAsCStrings strs m =+ foldr (\str k cstrs -> BS.useAsCString str $ \cstr -> k (cstr:cstrs)) m strs []++-- | Create a new JVM, with the given arguments. /Can only be called once/. Best+-- practice: use it to wrap your @main@ function.+withJVM :: [ByteString] -> IO a -> IO a+withJVM options action =+ bracket ini fini (const action)+ where+ ini = do+ useAsCStrings options $ \cstrs -> do+ withArray cstrs $ \(coptions :: Ptr (Ptr CChar)) -> do+ let n = fromIntegral (length cstrs) :: C.CInt+ [C.block| JavaVM * {+ JavaVM *jvm;+ JNIEnv *env;+ JavaVMInitArgs vm_args;+ JavaVMOption *options = malloc(sizeof(JavaVMOption) * $(int n));+ for(int i = 0; i < $(int n); i++)+ options[i].optionString = $(char **coptions)[i];+ vm_args.version = JNI_VERSION_1_6;+ vm_args.nOptions = $(int n);+ vm_args.options = options;+ vm_args.ignoreUnrecognized = 0;+ JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);+ free(options);+ return jvm; } |]+ fini jvm = do+ acquireWriteLock globalJVMLock+ [C.block| void { (*$(JavaVM *jvm))->DestroyJavaVM($(JavaVM *jvm)); } |]++defineClass+ :: Coercible o (J ('Class "java.lang.ClassLoader"))+ => JNI.String -- ^ Class name+ -> o -- ^ Loader+ -> ByteString -- ^ Bytecode buffer+ -> IO JClass+defineClass name (coerce -> upcast -> loader) buf = withJNIEnv $ \env ->+ throwIfException env $+ JNI.withString name $ \namep ->+ objectFromPtr =<<+ [CU.exp| jclass {+ (*$(JNIEnv *env))->DefineClass($(JNIEnv *env),+ $(char *namep),+ $fptr-ptr:(jobject loader),+ $bs-ptr:buf,+ $bs-len:buf) } |]+registerNatives+ :: JClass+ -> [JNINativeMethod]+ -> IO ()+registerNatives cls methods = withJNIEnv $ \env ->+ throwIfException env $+ withArray methods $ \cmethods -> do+ let numMethods = fromIntegral $ length methods+ _ <- [CU.exp| jint {+ (*$(JNIEnv *env))->RegisterNatives($(JNIEnv *env),+ $fptr-ptr:(jclass cls),+ $(JNINativeMethod *cmethods),+ $(int numMethods)) } |]+ return ()++throw :: Coercible o (J a) => o -> IO ()+throw (coerce -> upcast -> obj) = withJNIEnv $ \env -> void $ do+ [CU.exp| jint {+ (*$(JNIEnv *env))->Throw($(JNIEnv *env),+ $fptr-ptr:(jobject obj)) } |]++throwNew :: JClass -> JNI.String -> IO ()+throwNew cls msg = withJNIEnv $ \env ->+ JNI.withString msg $ \msgp -> void $ do+ [CU.exp| jint {+ (*$(JNIEnv *env))->ThrowNew($(JNIEnv *env),+ $fptr-ptr:(jclass cls),+ $(char *msgp)) } |]++findClass+ :: JNI.String -- ^ Class name+ -> IO JClass+findClass name = withJNIEnv $ \env ->+ throwIfException env $+ JNI.withString name $ \namep ->+ objectFromPtr =<<+ [CU.exp| jclass { (*$(JNIEnv *env))->FindClass($(JNIEnv *env), $(char *namep)) } |]++newObject :: JClass -> JNI.String -> [JValue] -> IO JObject+newObject cls sig args = withJNIEnv $ \env ->+ throwIfException env $+ withJValues args $ \cargs -> do+ constr <- getMethodID cls "<init>" sig+ objectFromPtr =<< [CU.exp| jobject {+ (*$(JNIEnv *env))->NewObjectA($(JNIEnv *env),+ $fptr-ptr:(jclass cls),+ $(jmethodID constr),+ $(jvalue *cargs)) } |]++getFieldID+ :: JClass -- ^ A class object as returned by 'findClass'+ -> JNI.String -- ^ Field name+ -> JNI.String -- ^ JNI signature+ -> IO JFieldID+getFieldID cls fieldname sig = withJNIEnv $ \env ->+ throwIfException env $+ JNI.withString fieldname $ \fieldnamep ->+ JNI.withString sig $ \sigp ->+ [CU.exp| jfieldID {+ (*$(JNIEnv *env))->GetFieldID($(JNIEnv *env),+ $fptr-ptr:(jclass cls),+ $(char *fieldnamep),+ $(char *sigp)) } |]++getStaticFieldID+ :: JClass -- ^ A class object as returned by 'findClass'+ -> JNI.String -- ^ Field name+ -> JNI.String -- ^ JNI signature+ -> IO JFieldID+getStaticFieldID cls fieldname sig = withJNIEnv $ \env ->+ throwIfException env $+ JNI.withString fieldname $ \fieldnamep ->+ JNI.withString sig $ \sigp ->+ [CU.exp| jfieldID {+ (*$(JNIEnv *env))->GetStaticFieldID($(JNIEnv *env),+ $fptr-ptr:(jclass cls),+ $(char *fieldnamep),+ $(char *sigp)) } |]++#define GET_FIELD(name, hs_rettype, c_rettype) \+get/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> IO hs_rettype; \+get/**/name/**/Field (coerce -> upcast -> obj) field = withJNIEnv $ \env -> \+ throwIfException env $ \+ [CU.exp| c_rettype { \+ (*$(JNIEnv *env))->Get/**/name/**/Field($(JNIEnv *env), \+ $fptr-ptr:(jobject obj), \+ $(jfieldID field)) } |]++getObjectField :: Coercible o (J a) => o -> JFieldID -> IO JObject+getObjectField x y =+ let GET_FIELD(Object, (Ptr JObject), jobject)+ in objectFromPtr =<< getObjectField x y+GET_FIELD(Boolean, Word8, jboolean)+GET_FIELD(Byte, CChar, jbyte)+GET_FIELD(Char, Word16, jchar)+GET_FIELD(Short, Int16, jshort)+GET_FIELD(Int, Int32, jint)+GET_FIELD(Long, Int64, jlong)+GET_FIELD(Float, Float, jfloat)+GET_FIELD(Double, Double, jdouble)++#define GET_STATIC_FIELD(name, hs_rettype, c_rettype) \+getStatic/**/name/**/Field :: JClass -> JFieldID -> IO hs_rettype; \+getStatic/**/name/**/Field klass field = withJNIEnv $ \env -> \+ throwIfException env $ \+ [CU.exp| c_rettype { \+ (*$(JNIEnv *env))->GetStatic/**/name/**/Field($(JNIEnv *env), \+ $fptr-ptr:(jclass klass), \+ $(jfieldID field)) } |]++getStaticObjectField :: JClass -> JFieldID -> IO JObject+getStaticObjectField x y =+ let GET_STATIC_FIELD(Object, (Ptr JObject), jobject)+ in objectFromPtr =<< getStaticObjectField x y+GET_STATIC_FIELD(Boolean, Word8, jboolean)+GET_STATIC_FIELD(Byte, CChar, jbyte)+GET_STATIC_FIELD(Char, Word16, jchar)+GET_STATIC_FIELD(Short, Int16, jshort)+GET_STATIC_FIELD(Int, Int32, jint)+GET_STATIC_FIELD(Long, Int64, jlong)+GET_STATIC_FIELD(Float, Float, jfloat)+GET_STATIC_FIELD(Double, Double, jdouble)++#define SET_FIELD(name, hs_fieldtype, c_fieldtype) \+set/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> hs_fieldtype -> IO (); \+set/**/name/**/Field (coerce -> upcast -> obj) field x = \+ withJNIEnv $ \env -> \+ throwIfException env $ \+ [CU.block| void { \+ (*$(JNIEnv *env))->Set/**/name/**/Field($(JNIEnv *env), \+ $fptr-ptr:(jobject obj), \+ $(jfieldID field), \+ $(c_fieldtype x)); } |]++setObjectField :: Coercible o (J a) => o -> JFieldID -> JObject -> IO ()+setObjectField x y z =+ let SET_FIELD(Object, (Ptr JObject), jobject)+ in withForeignPtr (coerce z) (setObjectField x y)+SET_FIELD(Boolean, Word8, jboolean)+SET_FIELD(Byte, CChar, jbyte)+SET_FIELD(Char, Word16, jchar)+SET_FIELD(Short, Int16, jshort)+SET_FIELD(Int, Int32, jint)+SET_FIELD(Long, Int64, jlong)+SET_FIELD(Float, Float, jfloat)+SET_FIELD(Double, Double, jdouble)++#define SET_STATIC_FIELD(name, hs_fieldtype, c_fieldtype) \+setStatic/**/name/**/Field :: JClass -> JFieldID -> hs_fieldtype -> IO (); \+setStatic/**/name/**/Field klass field x = \+ withJNIEnv $ \env -> \+ throwIfException env $ \+ [CU.block| void { \+ (*$(JNIEnv *env))->SetStatic/**/name/**/Field($(JNIEnv *env), \+ $fptr-ptr:(jclass klass), \+ $(jfieldID field), \+ $(c_fieldtype x)); } |]++setStaticObjectField :: JClass -> JFieldID -> JObject -> IO ()+setStaticObjectField x y z =+ let SET_STATIC_FIELD(Object, (Ptr JObject), jobject)+ in withForeignPtr (coerce z) (setStaticObjectField x y)+SET_STATIC_FIELD(Boolean, Word8, jboolean)+SET_STATIC_FIELD(Byte, CChar, jbyte)+SET_STATIC_FIELD(Char, Word16, jchar)+SET_STATIC_FIELD(Short, Int16, jshort)+SET_STATIC_FIELD(Int, Int32, jint)+SET_STATIC_FIELD(Long, Int64, jlong)+SET_STATIC_FIELD(Float, Float, jfloat)+SET_STATIC_FIELD(Double, Double, jdouble)++getMethodID+ :: JClass -- ^ A class object as returned by 'findClass'+ -> JNI.String -- ^ Field name+ -> JNI.String -- ^ JNI signature+ -> IO JMethodID+getMethodID cls methodname sig = withJNIEnv $ \env ->+ throwIfException env $+ JNI.withString methodname $ \methodnamep ->+ JNI.withString sig $ \sigp ->+ [CU.exp| jmethodID {+ (*$(JNIEnv *env))->GetMethodID($(JNIEnv *env),+ $fptr-ptr:(jclass cls),+ $(char *methodnamep),+ $(char *sigp)) } |]++getStaticMethodID+ :: JClass -- ^ A class object as returned by 'findClass'+ -> JNI.String -- ^ Field name+ -> JNI.String -- ^ JNI signature+ -> IO JMethodID+getStaticMethodID cls methodname sig = withJNIEnv $ \env ->+ throwIfException env $+ JNI.withString methodname $ \methodnamep ->+ JNI.withString sig $ \sigp ->+ [CU.exp| jmethodID {+ (*$(JNIEnv *env))->GetStaticMethodID($(JNIEnv *env),+ $fptr-ptr:(jclass cls),+ $(char *methodnamep),+ $(char *sigp)) } |]++getObjectClass :: Coercible o (J ty) => o -> IO JClass+getObjectClass (coerce -> upcast -> obj) = withJNIEnv $ \env ->+ objectFromPtr =<<+ [CU.exp| jclass {+ (*$(JNIEnv *env))->GetObjectClass($(JNIEnv *env),+ $fptr-ptr:(jobject obj)) } |]++-- | Creates a global reference to the object referred to by+-- the given reference.+--+-- Arranges for a finalizer to call 'deleteGlobalRef' when the+-- global reference is no longer reachable on the Haskell side.+newGlobalRef :: Coercible o (J ty) => o -> IO o+newGlobalRef (coerce -> upcast -> obj) = withJNIEnv $ \env -> do+ gobj <-+ [CU.exp| jobject {+ (*$(JNIEnv *env))->NewGlobalRef($(JNIEnv *env),+ $fptr-ptr:(jobject obj)) } |]+ coerce <$> J <$> newConcForeignPtr gobj (finalize gobj)+ where+ finalize gobj = do+ bracket (tryAcquireReadLock globalJVMLock)+ (\doRead -> when (toBool doRead) $ releaseReadLock globalJVMLock)+ $ \doRead ->+ when (toBool doRead) $ withJNIEnv $ \env ->+ [CU.block| void { (*$(JNIEnv *env))->DeleteGlobalRef($(JNIEnv *env)+ ,$(jobject gobj));+ } |]++deleteGlobalRef :: Coercible o (J ty) => o -> IO ()+deleteGlobalRef (coerce -> J p) = finalizeForeignPtr p++-- NB: Cannot add a finalizer to local references because it may+-- run in a thread where the reference is not valid.+newLocalRef :: Coercible o (J ty) => o -> IO (J ty)+newLocalRef (coerce -> upcast -> obj) = withJNIEnv $ \env ->+ unsafeCast <$> (objectFromPtr =<<)+ [CU.exp| jobject {+ (*$(JNIEnv *env))->NewLocalRef($(JNIEnv *env),+ $fptr-ptr:(jobject obj)) } |]++deleteLocalRef :: Coercible o (J ty) => o -> IO ()+deleteLocalRef (coerce -> upcast -> obj) = withJNIEnv $ \env ->+ [CU.exp| void {+ (*$(JNIEnv *env))->DeleteLocalRef($(JNIEnv *env),+ $fptr-ptr:(jobject obj)) } |]++pushLocalFrame :: Int32 -> IO ()+pushLocalFrame (coerce -> capacity) = withJNIEnv $ \env ->+ -- We ignore the output as it is always 0 on success and throws an+ -- exception otherwise.+ throwIfException env $ void $+ [CU.block| jint {+ (*$(JNIEnv *env))->PushLocalFrame($(JNIEnv *env),+ $(jint capacity)); } |]++popLocalFrame :: Coercible o (J ty) => o -> IO o+popLocalFrame (coerce -> upcast -> obj) = withJNIEnv $ \env ->+ coerce <$> (objectFromPtr =<<)+ [CU.exp| jobject {+ (*$(JNIEnv *env))->PopLocalFrame($(JNIEnv *env),+ $fptr-ptr:(jobject obj)) } |]++-- Modern CPP does have ## for concatenating strings, but we use the hacky /**/+-- comment syntax for string concatenation. This is because GHC passes+-- the -traditional flag to the preprocessor by default, which turns off several+-- modern CPP features.++#define CALL_METHOD(name, hs_rettype, c_rettype) \+call/**/name/**/Method :: Coercible o (J a) => o -> JMethodID -> [JValue] -> IO hs_rettype; \+call/**/name/**/Method (coerce -> upcast -> obj) method args = withJNIEnv $ \env -> \+ throwIfException env $ \+ withJValues args $ \cargs -> \+ [C.exp| c_rettype { \+ (*$(JNIEnv *env))->Call/**/name/**/MethodA($(JNIEnv *env), \+ $fptr-ptr:(jobject obj), \+ $(jmethodID method), \+ $(jvalue *cargs)) } |]++CALL_METHOD(Void, (), void)+callObjectMethod :: Coercible o (J a) => o -> JMethodID -> [JValue] -> IO JObject+callObjectMethod x y z =+ let CALL_METHOD(Object, (Ptr JObject), jobject)+ in objectFromPtr =<< callObjectMethod x y z+callBooleanMethod :: Coercible o (J a) => o -> JMethodID -> [JValue] -> IO Bool+callBooleanMethod x y z =+ let CALL_METHOD(Boolean, Word8, jboolean)+ in toEnum . fromIntegral <$> callBooleanMethod x y z+CALL_METHOD(Byte, CChar, jbyte)+CALL_METHOD(Char, Word16, jchar)+CALL_METHOD(Short, Int16, jshort)+CALL_METHOD(Int, Int32, jint)+CALL_METHOD(Long, Int64, jlong)+CALL_METHOD(Float, Float, jfloat)+CALL_METHOD(Double, Double, jdouble)++#define CALL_STATIC_METHOD(name, hs_rettype, c_rettype) \+callStatic/**/name/**/Method :: JClass -> JMethodID -> [JValue] -> IO hs_rettype; \+callStatic/**/name/**/Method cls method args = withJNIEnv $ \env -> \+ throwIfException env $ \+ withJValues args $ \cargs -> \+ [C.exp| c_rettype { \+ (*$(JNIEnv *env))->CallStatic/**/name/**/MethodA($(JNIEnv *env), \+ $fptr-ptr:(jclass cls), \+ $(jmethodID method), \+ $(jvalue *cargs)) } |]++CALL_STATIC_METHOD(Void, (), void)+callStaticObjectMethod :: JClass -> JMethodID -> [JValue] -> IO JObject+callStaticObjectMethod x y z =+ let CALL_STATIC_METHOD(Object, (Ptr JObject), jobject)+ in objectFromPtr =<< callStaticObjectMethod x y z+callStaticBooleanMethod :: JClass -> JMethodID -> [JValue] -> IO Bool+callStaticBooleanMethod x y z =+ let CALL_STATIC_METHOD(Boolean, Word8, jboolean)+ in toEnum . fromIntegral <$> callStaticBooleanMethod x y z+CALL_STATIC_METHOD(Byte, CChar, jbyte)+CALL_STATIC_METHOD(Char, Word16, jchar)+CALL_STATIC_METHOD(Short, Int16, jshort)+CALL_STATIC_METHOD(Int, Int32, jint)+CALL_STATIC_METHOD(Long, Int64, jlong)+CALL_STATIC_METHOD(Float, Float, jfloat)+CALL_STATIC_METHOD(Double, Double, jdouble)++newObjectArray :: Int32 -> JClass -> IO JObjectArray+newObjectArray sz cls = withJNIEnv $ \env ->+ throwIfException env $+ objectFromPtr =<<+ [CU.exp| jobjectArray {+ (*$(JNIEnv *env))->NewObjectArray($(JNIEnv *env),+ $(jsize sz),+ $fptr-ptr:(jclass cls),+ NULL) } |]++#define NEW_ARRAY(name, c_rettype) \+new/**/name/**/Array :: Int32 -> IO J/**/name/**/Array; \+new/**/name/**/Array sz = withJNIEnv $ \env -> \+ throwIfException env $ \+ objectFromPtr =<< \+ [CU.exp| c_rettype/**/Array { \+ (*$(JNIEnv *env))->New/**/name/**/Array($(JNIEnv *env), \+ $(jsize sz)) } |]++NEW_ARRAY(Boolean, jboolean)+NEW_ARRAY(Byte, jbyte)+NEW_ARRAY(Char, jchar)+NEW_ARRAY(Short, jshort)+NEW_ARRAY(Int, jint)+NEW_ARRAY(Long, jlong)+NEW_ARRAY(Float, jfloat)+NEW_ARRAY(Double, jdouble)++newString :: Ptr Word16 -> Int32 -> IO JString+newString ptr len = withJNIEnv $ \env ->+ throwIfException env $+ objectFromPtr =<<+ [CU.exp| jstring {+ (*$(JNIEnv *env))->NewString($(JNIEnv *env),+ $(jchar *ptr),+ $(jsize len)) } |]++getArrayLength :: Coercible o (JArray a) => o -> IO Int32+getArrayLength (coerce -> upcast -> array) = withJNIEnv $ \env ->+ [C.exp| jsize {+ (*$(JNIEnv *env))->GetArrayLength($(JNIEnv *env),+ $fptr-ptr:(jarray array)) } |]++getStringLength :: JString -> IO Int32+getStringLength jstr = withJNIEnv $ \env ->+ [CU.exp| jsize {+ (*$(JNIEnv *env))->GetStringLength($(JNIEnv *env),+ $fptr-ptr:(jstring jstr)) } |]++#define GET_ARRAY_ELEMENTS(name, hs_rettype, c_rettype) \+get/**/name/**/ArrayElements :: J/**/name/**/Array -> IO (Ptr hs_rettype); \+get/**/name/**/ArrayElements (upcast -> array) = withJNIEnv $ \env -> \+ throwIfNull $ \+ [CU.exp| c_rettype* { \+ (*$(JNIEnv *env))->Get/**/name/**/ArrayElements($(JNIEnv *env), \+ $fptr-ptr:(jobject array), \+ NULL) } |]++GET_ARRAY_ELEMENTS(Boolean, Word8, jboolean)+GET_ARRAY_ELEMENTS(Byte, CChar, jbyte)+GET_ARRAY_ELEMENTS(Char, Word16, jchar)+GET_ARRAY_ELEMENTS(Short, Int16, jshort)+GET_ARRAY_ELEMENTS(Int, Int32, jint)+GET_ARRAY_ELEMENTS(Long, Int64, jlong)+GET_ARRAY_ELEMENTS(Float, Float, jfloat)+GET_ARRAY_ELEMENTS(Double, Double, jdouble)++getStringChars :: JString -> IO (Ptr Word16)+getStringChars jstr = withJNIEnv $ \env ->+ throwIfNull $+ [CU.exp| const jchar* {+ (*$(JNIEnv *env))->GetStringChars($(JNIEnv *env),+ $fptr-ptr:(jstring jstr),+ NULL) } |]++#define SET_ARRAY_REGION(name, hs_argtype, c_argtype) \+set/**/name/**/ArrayRegion :: J/**/name/**/Array -> Int32 -> Int32 -> Ptr hs_argtype -> IO (); \+set/**/name/**/ArrayRegion array start len buf = withJNIEnv $ \env -> \+ throwIfException env $ \+ [CU.exp| void { \+ (*$(JNIEnv *env))->Set/**/name/**/ArrayRegion($(JNIEnv *env), \+ $fptr-ptr:(c_argtype/**/Array array), \+ $(jsize start), \+ $(jsize len), \+ $(c_argtype *buf)) } |]++SET_ARRAY_REGION(Boolean, Word8, jboolean)+SET_ARRAY_REGION(Byte, CChar, jbyte)+SET_ARRAY_REGION(Char, Word16, jchar)+SET_ARRAY_REGION(Short, Int16, jshort)+SET_ARRAY_REGION(Int, Int32, jint)+SET_ARRAY_REGION(Long, Int64, jlong)+SET_ARRAY_REGION(Float, Float, jfloat)+SET_ARRAY_REGION(Double, Double, jdouble)++#define RELEASE_ARRAY_ELEMENTS(name, hs_argtype, c_argtype) \+release/**/name/**/ArrayElements :: J/**/name/**/Array -> Ptr hs_argtype -> IO (); \+release/**/name/**/ArrayElements (upcast -> array) xs = withJNIEnv $ \env -> \+ [CU.exp| void { \+ (*$(JNIEnv *env))->Release/**/name/**/ArrayElements($(JNIEnv *env), \+ $fptr-ptr:(jobject array), \+ $(c_argtype *xs), \+ JNI_ABORT) } |]++RELEASE_ARRAY_ELEMENTS(Boolean, Word8, jboolean)+RELEASE_ARRAY_ELEMENTS(Byte, CChar, jbyte)+RELEASE_ARRAY_ELEMENTS(Char, Word16, jchar)+RELEASE_ARRAY_ELEMENTS(Short, Int16, jshort)+RELEASE_ARRAY_ELEMENTS(Int, Int32, jint)+RELEASE_ARRAY_ELEMENTS(Long, Int64, jlong)+RELEASE_ARRAY_ELEMENTS(Float, Float, jfloat)+RELEASE_ARRAY_ELEMENTS(Double, Double, jdouble)++releaseStringChars :: JString -> Ptr Word16 -> IO ()+releaseStringChars jstr chars = withJNIEnv $ \env ->+ [CU.exp| void {+ (*$(JNIEnv *env))->ReleaseStringChars($(JNIEnv *env),+ $fptr-ptr:(jstring jstr),+ $(jchar *chars)) } |]++getObjectArrayElement :: Coercible o (JArray a) => o -> Int32 -> IO (J a)+getObjectArrayElement (coerce -> upcast -> array) i = withJNIEnv $ \env ->+ unsafeCast <$> (objectFromPtr =<<)+ [C.exp| jobject {+ (*$(JNIEnv *env))->GetObjectArrayElement($(JNIEnv *env),+ $fptr-ptr:(jarray array),+ $(jsize i)) } |]++setObjectArrayElement :: Coercible o (J a) => JObjectArray -> Int32 -> o -> IO ()+setObjectArrayElement array i (coerce -> upcast -> x) = withJNIEnv $ \env ->+ [C.exp| void {+ (*$(JNIEnv *env))->SetObjectArrayElement($(JNIEnv *env),+ $fptr-ptr:(jobjectArray array),+ $(jsize i),+ $fptr-ptr:(jobject x)); } |]
− src/Foreign/JNI.hs
@@ -1,686 +0,0 @@--- | Low-level bindings to the Java Native Interface (JNI).------ Read the--- <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html JNI spec>--- for authoritative documentation as to what each of the functions in--- this module does. The names of the bindings in this module were chosen to--- match the names of the functions in the JNI spec.------ All bindings in this module access the JNI via a thread-local variable of--- type @JNIEnv *@. If the current OS thread has not yet been "attached" to the--- JVM, it is attached implicitly upon the first call to one of these bindings--- in the current thread.------ The 'String' type in this module is the type of JNI strings. See "Foreign.JNI.String".-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExplicitNamespaces #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}--{-# OPTIONS_GHC -fno-warn-name-shadowing #-}--module Foreign.JNI- ( -- * JNI functions- -- ** VM creation- withJVM- -- ** Class loading- , defineClass- , JNINativeMethod(..)- , registerNatives- -- ** Exceptions- , throw- , throwNew- -- ** Query functions- , findClass- , getFieldID- , getStaticFieldID- , getMethodID- , getStaticMethodID- , getObjectClass- -- ** Reference manipulation- , newGlobalRef- , deleteGlobalRef- -- ** Field accessor functions- -- *** Get fields- , getObjectField- , getBooleanField- , getIntField- , getLongField- , getCharField- , getShortField- , getByteField- , getDoubleField- , getFloatField- -- *** Get static fields- , getStaticObjectField- , getStaticBooleanField- , getStaticIntField- , getStaticLongField- , getStaticCharField- , getStaticShortField- , getStaticByteField- , getStaticDoubleField- , getStaticFloatField- -- *** Set fields- , setObjectField- , setBooleanField- , setIntField- , setLongField- , setCharField- , setShortField- , setByteField- , setDoubleField- , setFloatField- -- *** Set static fields- , setStaticObjectField- , setStaticBooleanField- , setStaticIntField- , setStaticLongField- , setStaticCharField- , setStaticShortField- , setStaticByteField- , setStaticDoubleField- , setStaticFloatField- -- ** Method invocation- , callObjectMethod- , callBooleanMethod- , callIntMethod- , callLongMethod- , callCharMethod- , callShortMethod- , callByteMethod- , callDoubleMethod- , callFloatMethod- , callVoidMethod- , callStaticObjectMethod- , callStaticVoidMethod- , callStaticBooleanMethod- , callStaticIntMethod- , callStaticLongMethod- , callStaticCharMethod- , callStaticShortMethod- , callStaticByteMethod- , callStaticDoubleMethod- , callStaticFloatMethod- -- ** Object construction- , newObject- , newString- , newObjectArray- , newBooleanArray- , newByteArray- , newCharArray- , newShortArray- , newIntArray- , newLongArray- , newFloatArray- , newDoubleArray- -- ** Array manipulation- , getArrayLength- , getStringLength- , getBooleanArrayElements- , getByteArrayElements- , getCharArrayElements- , getShortArrayElements- , getIntArrayElements- , getLongArrayElements- , getFloatArrayElements- , getDoubleArrayElements- , getStringChars- , setBooleanArrayRegion- , setByteArrayRegion- , setCharArrayRegion- , setShortArrayRegion- , setIntArrayRegion- , setLongArrayRegion- , setFloatArrayRegion- , setDoubleArrayRegion- , releaseBooleanArrayElements- , releaseByteArrayElements- , releaseCharArrayElements- , releaseShortArrayElements- , releaseIntArrayElements- , releaseLongArrayElements- , releaseFloatArrayElements- , releaseDoubleArrayElements- , releaseStringChars- , getObjectArrayElement- , setObjectArrayElement- ) where--import Control.Exception (Exception, bracket, finally, throwIO)-import Control.Monad (unless, void)-import Data.Coerce-import Data.Int-import Data.IORef (IORef, newIORef, readIORef)-import Data.Word-import Data.ByteString (ByteString)-import qualified Data.ByteString as BS-import Data.Monoid ((<>))-import Data.Typeable (Typeable)-import Data.TLS.PThread-import Foreign.C (CChar)-import Foreign.JNI.NativeMethod-import Foreign.JNI.Types-import qualified Foreign.JNI.String as JNI-import Foreign.Marshal.Array-import Foreign.Ptr (Ptr, nullPtr)-import qualified Language.C.Inline as C-import qualified Language.C.Inline.Unsafe as CU-import System.IO.Unsafe (unsafePerformIO)-import Prelude hiding (String)--C.context (C.baseCtx <> C.bsCtx <> jniCtx)--C.include "<jni.h>"-C.include "<errno.h>"-C.include "<stdlib.h>"--data JavaException = JavaException JThrowable- deriving (Show, Typeable)--instance Exception JavaException---- | Thrown when @Get<PrimitiveType>ArrayElements@ returns a null pointer,--- because it wanted to copy the array contents but couldn't. In this case the--- JVM doesn't throw OutOfMemory according to the JNI spec.-data ArrayCopyFailed = ArrayCopyFailed- deriving (Show, Typeable)--instance Exception ArrayCopyFailed---- | Map Java exceptions to Haskell exceptions.-throwIfException :: Ptr JNIEnv -> IO a -> IO a-throwIfException env m = m `finally` do- J excptr <- [CU.exp| jthrowable { (*$(JNIEnv *env))->ExceptionOccurred($(JNIEnv *env)) } |]- unless (excptr == nullPtr) $ do- [CU.exp| void { (*$(JNIEnv *env))->ExceptionDescribe($(JNIEnv *env)) } |]- [CU.exp| void { (*$(JNIEnv *env))->ExceptionClear($(JNIEnv *env)) } |]- throwIO $ JavaException (J excptr)---- | Check whether a pointer is null.-throwIfNull :: IO (Ptr a) -> IO (Ptr a)-throwIfNull m = do- ptr <- m- if ptr == nullPtr- then throwIO ArrayCopyFailed- else return ptr---- | A global mutable cell holding the TLS variable, whose content is set once--- for each thread.-envTlsRef :: IORef (TLS (Ptr JNIEnv))-{-# NOINLINE envTlsRef #-}-envTlsRef = unsafePerformIO $ do- -- It doesn't matter if this computation ends up running twice, say because- -- of lazy blackholing.- !tls <- mkTLS $ [C.block| JNIEnv* {- jsize num_jvms;- JavaVM *jvm;- /* Assume there's at most one JVM. The current JNI spec (2016) says only- * one JVM per process is supported anyways. */- JNI_GetCreatedJavaVMs(&jvm, 1, &num_jvms);- JNIEnv *env;-- if(!num_jvms) {- fprintf(stderr, "No JVM has been initialized yet.\n");- exit(EFAULT);- }-- /* Attach as daemon to match GHC's usual semantics for threads, which are- * daemonic.- */- (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void**)&env, NULL);- return env; } |]- newIORef tls---- | Run an action against the appropriate 'JNIEnv'.------ Each OS thread has its own 'JNIEnv', which this function gives access to.------ TODO check whether this call is only safe from a (bound) thread.-withJNIEnv :: (Ptr JNIEnv -> IO a) -> IO a-withJNIEnv f = f =<< getTLS =<< readIORef envTlsRef--useAsCStrings :: [ByteString] -> ([Ptr CChar] -> IO a) -> IO a-useAsCStrings strs m =- foldr (\str k cstrs -> BS.useAsCString str $ \cstr -> k (cstr:cstrs)) m strs []---- | Create a new JVM, with the given arguments. /Can only be called once/. Best--- practice: use it to wrap your @main@ function.-withJVM :: [ByteString] -> IO a -> IO a-withJVM options action =- bracket ini fini (const action)- where- ini = do- useAsCStrings options $ \cstrs -> do- withArray cstrs $ \(coptions :: Ptr (Ptr CChar)) -> do- let n = fromIntegral (length cstrs) :: C.CInt- [C.block| JavaVM * {- JavaVM *jvm;- JNIEnv *env;- JavaVMInitArgs vm_args;- JavaVMOption *options = malloc(sizeof(JavaVMOption) * $(int n));- for(int i = 0; i < $(int n); i++)- options[i].optionString = $(char **coptions)[i];- vm_args.version = JNI_VERSION_1_6;- vm_args.nOptions = $(int n);- vm_args.options = options;- vm_args.ignoreUnrecognized = 0;- JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);- free(options);- return jvm; } |]- fini jvm = [C.block| void { (*$(JavaVM *jvm))->DestroyJavaVM($(JavaVM *jvm)); } |]--defineClass- :: Coercible o (J ('Class "java.lang.ClassLoader"))- => JNI.String -- ^ Class name- -> o -- ^ Loader- -> ByteString -- ^ Bytecode buffer- -> IO JClass-defineClass name (coerce -> upcast -> loader) buf = withJNIEnv $ \env ->- throwIfException env $- JNI.withString name $ \namep ->- [CU.exp| jclass {- (*$(JNIEnv *env))->DefineClass($(JNIEnv *env),- $(char *namep),- $(jobject loader),- $bs-ptr:buf,- $bs-len:buf) } |]-registerNatives- :: JClass- -> [JNINativeMethod]- -> IO ()-registerNatives cls methods = withJNIEnv $ \env ->- throwIfException env $- withArray methods $ \cmethods -> do- let numMethods = fromIntegral $ length methods- _ <- [CU.exp| jint {- (*$(JNIEnv *env))->RegisterNatives($(JNIEnv *env),- $(jclass cls),- $(JNINativeMethod *cmethods),- $(int numMethods)) } |]- return ()--throw :: Coercible o (J a) => o -> IO ()-throw (coerce -> upcast -> obj) = withJNIEnv $ \env -> void $ do- [CU.exp| jint {- (*$(JNIEnv *env))->Throw($(JNIEnv *env),- $(jobject obj)) } |]--throwNew :: JClass -> JNI.String -> IO ()-throwNew cls msg = withJNIEnv $ \env ->- JNI.withString msg $ \msgp -> void $ do- [CU.exp| jint {- (*$(JNIEnv *env))->ThrowNew($(JNIEnv *env),- $(jclass cls),- $(char *msgp)) } |]--findClass- :: JNI.String -- ^ Class name- -> IO JClass-findClass name = withJNIEnv $ \env ->- throwIfException env $- JNI.withString name $ \namep ->- [CU.exp| jclass { (*$(JNIEnv *env))->FindClass($(JNIEnv *env), $(char *namep)) } |]--newObject :: JClass -> JNI.String -> [JValue] -> IO JObject-newObject cls sig args = withJNIEnv $ \env ->- throwIfException env $- withArray args $ \cargs -> do- constr <- getMethodID cls "<init>" sig- [CU.exp| jobject {- (*$(JNIEnv *env))->NewObjectA($(JNIEnv *env),- $(jclass cls),- $(jmethodID constr),- $(jvalue *cargs)) } |]--getFieldID- :: JClass -- ^ A class object as returned by 'findClass'- -> JNI.String -- ^ Field name- -> JNI.String -- ^ JNI signature- -> IO JFieldID-getFieldID cls fieldname sig = withJNIEnv $ \env ->- throwIfException env $- JNI.withString fieldname $ \fieldnamep ->- JNI.withString sig $ \sigp ->- [CU.exp| jfieldID {- (*$(JNIEnv *env))->GetFieldID($(JNIEnv *env),- $(jclass cls),- $(char *fieldnamep),- $(char *sigp)) } |]--getStaticFieldID- :: JClass -- ^ A class object as returned by 'findClass'- -> JNI.String -- ^ Field name- -> JNI.String -- ^ JNI signature- -> IO JFieldID-getStaticFieldID cls fieldname sig = withJNIEnv $ \env ->- throwIfException env $- JNI.withString fieldname $ \fieldnamep ->- JNI.withString sig $ \sigp ->- [CU.exp| jfieldID {- (*$(JNIEnv *env))->GetStaticFieldID($(JNIEnv *env),- $(jclass cls),- $(char *fieldnamep),- $(char *sigp)) } |]--#define GET_FIELD(name, hs_rettype, c_rettype) \-get/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> IO hs_rettype; \-get/**/name/**/Field (coerce -> upcast -> obj) field = withJNIEnv $ \env -> \- throwIfException env $ \- [CU.exp| c_rettype { \- (*$(JNIEnv *env))->Get/**/name/**/Field($(JNIEnv *env), \- $(jobject obj), \- $(jfieldID field)) } |]--GET_FIELD(Object, JObject, jobject)-GET_FIELD(Boolean, Word8, jboolean)-GET_FIELD(Byte, CChar, jbyte)-GET_FIELD(Char, Word16, jchar)-GET_FIELD(Short, Int16, jshort)-GET_FIELD(Int, Int32, jint)-GET_FIELD(Long, Int64, jlong)-GET_FIELD(Float, Float, jfloat)-GET_FIELD(Double, Double, jdouble)--#define GET_STATIC_FIELD(name, hs_rettype, c_rettype) \-getStatic/**/name/**/Field :: JClass -> JFieldID -> IO hs_rettype; \-getStatic/**/name/**/Field klass field = withJNIEnv $ \env -> \- throwIfException env $ \- [CU.exp| c_rettype { \- (*$(JNIEnv *env))->GetStatic/**/name/**/Field($(JNIEnv *env), \- $(jclass klass), \- $(jfieldID field)) } |]--GET_STATIC_FIELD(Object, JObject, jobject)-GET_STATIC_FIELD(Boolean, Word8, jboolean)-GET_STATIC_FIELD(Byte, CChar, jbyte)-GET_STATIC_FIELD(Char, Word16, jchar)-GET_STATIC_FIELD(Short, Int16, jshort)-GET_STATIC_FIELD(Int, Int32, jint)-GET_STATIC_FIELD(Long, Int64, jlong)-GET_STATIC_FIELD(Float, Float, jfloat)-GET_STATIC_FIELD(Double, Double, jdouble)--#define SET_FIELD(name, hs_fieldtype, c_fieldtype) \-set/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> hs_fieldtype -> IO (); \-set/**/name/**/Field (coerce -> upcast -> obj) field x = \- withJNIEnv $ \env -> \- throwIfException env $ \- [CU.block| void { \- (*$(JNIEnv *env))->Set/**/name/**/Field($(JNIEnv *env), \- $(jobject obj), \- $(jfieldID field), \- $(c_fieldtype x)); } |]--SET_FIELD(Object, JObject, jobject)-SET_FIELD(Boolean, Word8, jboolean)-SET_FIELD(Byte, CChar, jbyte)-SET_FIELD(Char, Word16, jchar)-SET_FIELD(Short, Int16, jshort)-SET_FIELD(Int, Int32, jint)-SET_FIELD(Long, Int64, jlong)-SET_FIELD(Float, Float, jfloat)-SET_FIELD(Double, Double, jdouble)--#define SET_STATIC_FIELD(name, hs_fieldtype, c_fieldtype) \-setStatic/**/name/**/Field :: JClass -> JFieldID -> hs_fieldtype -> IO (); \-setStatic/**/name/**/Field klass field x = \- withJNIEnv $ \env -> \- throwIfException env $ \- [CU.block| void { \- (*$(JNIEnv *env))->SetStatic/**/name/**/Field($(JNIEnv *env), \- $(jclass klass), \- $(jfieldID field), \- $(c_fieldtype x)); } |]--SET_STATIC_FIELD(Object, JObject, jobject)-SET_STATIC_FIELD(Boolean, Word8, jboolean)-SET_STATIC_FIELD(Byte, CChar, jbyte)-SET_STATIC_FIELD(Char, Word16, jchar)-SET_STATIC_FIELD(Short, Int16, jshort)-SET_STATIC_FIELD(Int, Int32, jint)-SET_STATIC_FIELD(Long, Int64, jlong)-SET_STATIC_FIELD(Float, Float, jfloat)-SET_STATIC_FIELD(Double, Double, jdouble)--getMethodID- :: JClass -- ^ A class object as returned by 'findClass'- -> JNI.String -- ^ Field name- -> JNI.String -- ^ JNI signature- -> IO JMethodID-getMethodID cls methodname sig = withJNIEnv $ \env ->- throwIfException env $- JNI.withString methodname $ \methodnamep ->- JNI.withString sig $ \sigp ->- [CU.exp| jmethodID {- (*$(JNIEnv *env))->GetMethodID($(JNIEnv *env),- $(jclass cls),- $(char *methodnamep),- $(char *sigp)) } |]--getStaticMethodID- :: JClass -- ^ A class object as returned by 'findClass'- -> JNI.String -- ^ Field name- -> JNI.String -- ^ JNI signature- -> IO JMethodID-getStaticMethodID cls methodname sig = withJNIEnv $ \env ->- throwIfException env $- JNI.withString methodname $ \methodnamep ->- JNI.withString sig $ \sigp ->- [CU.exp| jmethodID {- (*$(JNIEnv *env))->GetStaticMethodID($(JNIEnv *env),- $(jclass cls),- $(char *methodnamep),- $(char *sigp)) } |]--getObjectClass :: Coercible o (J ty) => o -> IO JClass-getObjectClass (coerce -> upcast -> obj) = withJNIEnv $ \env ->- [CU.exp| jclass {- (*$(JNIEnv *env))->GetObjectClass($(JNIEnv *env),- $(jobject obj)) } |]--newGlobalRef :: Coercible o (J ty) => o -> IO o-newGlobalRef (coerce -> upcast -> obj) = withJNIEnv $ \env ->- fmap coerce $- [CU.exp| jobject {- (*$(JNIEnv *env))->NewGlobalRef($(JNIEnv *env),- $(jobject obj)) } |]--deleteGlobalRef :: Coercible o (J ty) => o -> IO ()-deleteGlobalRef (coerce -> upcast -> obj) = withJNIEnv $ \env ->- [CU.block| void {- (*$(JNIEnv *env))->DeleteGlobalRef($(JNIEnv *env),- $(jobject obj)); } |]---- Modern CPP does have ## for concatenating strings, but we use the hacky /**/--- comment syntax for string concatenation. This is because GHC passes--- the -traditional flag to the preprocessor by default, which turns off several--- modern CPP features.--#define CALL_METHOD(name, hs_rettype, c_rettype) \-call/**/name/**/Method :: Coercible o (J a) => o -> JMethodID -> [JValue] -> IO hs_rettype; \-call/**/name/**/Method (coerce -> upcast -> obj) method args = withJNIEnv $ \env -> \- throwIfException env $ \- withArray args $ \cargs -> \- [C.exp| c_rettype { \- (*$(JNIEnv *env))->Call/**/name/**/MethodA($(JNIEnv *env), \- $(jobject obj), \- $(jmethodID method), \- $(jvalue *cargs)) } |]--CALL_METHOD(Void, (), void)-CALL_METHOD(Object, JObject, jobject)-callBooleanMethod :: Coercible o (J a) => o -> JMethodID -> [JValue] -> IO Bool-callBooleanMethod x y z =- let CALL_METHOD(Boolean, Word8, jboolean)- in toEnum . fromIntegral <$> callBooleanMethod x y z-CALL_METHOD(Byte, CChar, jbyte)-CALL_METHOD(Char, Word16, jchar)-CALL_METHOD(Short, Int16, jshort)-CALL_METHOD(Int, Int32, jint)-CALL_METHOD(Long, Int64, jlong)-CALL_METHOD(Float, Float, jfloat)-CALL_METHOD(Double, Double, jdouble)--#define CALL_STATIC_METHOD(name, hs_rettype, c_rettype) \-callStatic/**/name/**/Method :: JClass -> JMethodID -> [JValue] -> IO hs_rettype; \-callStatic/**/name/**/Method cls method args = withJNIEnv $ \env -> \- throwIfException env $ \- withArray args $ \cargs -> \- [C.exp| c_rettype { \- (*$(JNIEnv *env))->CallStatic/**/name/**/MethodA($(JNIEnv *env), \- $(jclass cls), \- $(jmethodID method), \- $(jvalue *cargs)) } |]--CALL_STATIC_METHOD(Void, (), void)-CALL_STATIC_METHOD(Object, JObject, jobject)-callStaticBooleanMethod :: JClass -> JMethodID -> [JValue] -> IO Bool-callStaticBooleanMethod x y z =- let CALL_STATIC_METHOD(Boolean, Word8, jboolean)- in toEnum . fromIntegral <$> callStaticBooleanMethod x y z-CALL_STATIC_METHOD(Byte, CChar, jbyte)-CALL_STATIC_METHOD(Char, Word16, jchar)-CALL_STATIC_METHOD(Short, Int16, jshort)-CALL_STATIC_METHOD(Int, Int32, jint)-CALL_STATIC_METHOD(Long, Int64, jlong)-CALL_STATIC_METHOD(Float, Float, jfloat)-CALL_STATIC_METHOD(Double, Double, jdouble)--newObjectArray :: Int32 -> JClass -> IO JObjectArray-newObjectArray sz cls = withJNIEnv $ \env ->- throwIfException env $- [CU.exp| jobjectArray {- (*$(JNIEnv *env))->NewObjectArray($(JNIEnv *env),- $(jsize sz),- $(jclass cls),- NULL) } |]--#define NEW_ARRAY(name, c_rettype) \-new/**/name/**/Array :: Int32 -> IO J/**/name/**/Array; \-new/**/name/**/Array sz = withJNIEnv $ \env -> \- throwIfException env $ \- [CU.exp| c_rettype/**/Array { \- (*$(JNIEnv *env))->New/**/name/**/Array($(JNIEnv *env), \- $(jsize sz)) } |]--NEW_ARRAY(Boolean, jboolean)-NEW_ARRAY(Byte, jbyte)-NEW_ARRAY(Char, jchar)-NEW_ARRAY(Short, jshort)-NEW_ARRAY(Int, jint)-NEW_ARRAY(Long, jlong)-NEW_ARRAY(Float, jfloat)-NEW_ARRAY(Double, jdouble)--newString :: Ptr Word16 -> Int32 -> IO JString-newString ptr len = withJNIEnv $ \env ->- throwIfException env $- [CU.exp| jstring {- (*$(JNIEnv *env))->NewString($(JNIEnv *env),- $(jchar *ptr),- $(jsize len)) } |]--getArrayLength :: Coercible o (JArray a) => o -> IO Int32-getArrayLength (coerce -> upcast -> array) = withJNIEnv $ \env ->- [C.exp| jsize {- (*$(JNIEnv *env))->GetArrayLength($(JNIEnv *env),- $(jarray array)) } |]--getStringLength :: JString -> IO Int32-getStringLength jstr = withJNIEnv $ \env ->- [CU.exp| jsize {- (*$(JNIEnv *env))->GetStringLength($(JNIEnv *env),- $(jstring jstr)) } |]--#define GET_ARRAY_ELEMENTS(name, hs_rettype, c_rettype) \-get/**/name/**/ArrayElements :: J/**/name/**/Array -> IO (Ptr hs_rettype); \-get/**/name/**/ArrayElements (upcast -> array) = withJNIEnv $ \env -> \- throwIfNull $ \- [CU.exp| c_rettype* { \- (*$(JNIEnv *env))->Get/**/name/**/ArrayElements($(JNIEnv *env), \- $(jobject array), \- NULL) } |]--GET_ARRAY_ELEMENTS(Boolean, Word8, jboolean)-GET_ARRAY_ELEMENTS(Byte, CChar, jbyte)-GET_ARRAY_ELEMENTS(Char, Word16, jchar)-GET_ARRAY_ELEMENTS(Short, Int16, jshort)-GET_ARRAY_ELEMENTS(Int, Int32, jint)-GET_ARRAY_ELEMENTS(Long, Int64, jlong)-GET_ARRAY_ELEMENTS(Float, Float, jfloat)-GET_ARRAY_ELEMENTS(Double, Double, jdouble)--getStringChars :: JString -> IO (Ptr Word16)-getStringChars jstr = withJNIEnv $ \env ->- throwIfNull $- [CU.exp| const jchar* {- (*$(JNIEnv *env))->GetStringChars($(JNIEnv *env),- $(jstring jstr),- NULL) } |]--#define SET_ARRAY_REGION(name, hs_argtype, c_argtype) \-set/**/name/**/ArrayRegion :: J/**/name/**/Array -> Int32 -> Int32 -> Ptr hs_argtype -> IO (); \-set/**/name/**/ArrayRegion array start len buf = withJNIEnv $ \env -> \- throwIfException env $ \- [CU.exp| void { \- (*$(JNIEnv *env))->Set/**/name/**/ArrayRegion($(JNIEnv *env), \- $(c_argtype/**/Array array), \- $(jsize start), \- $(jsize len), \- $(c_argtype *buf)) } |]--SET_ARRAY_REGION(Boolean, Word8, jboolean)-SET_ARRAY_REGION(Byte, CChar, jbyte)-SET_ARRAY_REGION(Char, Word16, jchar)-SET_ARRAY_REGION(Short, Int16, jshort)-SET_ARRAY_REGION(Int, Int32, jint)-SET_ARRAY_REGION(Long, Int64, jlong)-SET_ARRAY_REGION(Float, Float, jfloat)-SET_ARRAY_REGION(Double, Double, jdouble)--#define RELEASE_ARRAY_ELEMENTS(name, hs_argtype, c_argtype) \-release/**/name/**/ArrayElements :: J/**/name/**/Array -> Ptr hs_argtype -> IO (); \-release/**/name/**/ArrayElements (upcast -> array) xs = withJNIEnv $ \env -> \- [CU.exp| void { \- (*$(JNIEnv *env))->Release/**/name/**/ArrayElements($(JNIEnv *env), \- $(jobject array), \- $(c_argtype *xs), \- JNI_ABORT) } |]--RELEASE_ARRAY_ELEMENTS(Boolean, Word8, jboolean)-RELEASE_ARRAY_ELEMENTS(Byte, CChar, jbyte)-RELEASE_ARRAY_ELEMENTS(Char, Word16, jchar)-RELEASE_ARRAY_ELEMENTS(Short, Int16, jshort)-RELEASE_ARRAY_ELEMENTS(Int, Int32, jint)-RELEASE_ARRAY_ELEMENTS(Long, Int64, jlong)-RELEASE_ARRAY_ELEMENTS(Float, Float, jfloat)-RELEASE_ARRAY_ELEMENTS(Double, Double, jdouble)--releaseStringChars :: JString -> Ptr Word16 -> IO ()-releaseStringChars jstr chars = withJNIEnv $ \env ->- [CU.exp| void {- (*$(JNIEnv *env))->ReleaseStringChars($(JNIEnv *env),- $(jstring jstr),- $(jchar *chars)) } |]--getObjectArrayElement :: Coercible o (JArray a) => o -> Int32 -> IO (J a)-getObjectArrayElement (coerce -> upcast -> array) i = withJNIEnv $ \env -> unsafeCast <$>- [C.exp| jobject {- (*$(JNIEnv *env))->GetObjectArrayElement($(JNIEnv *env),- $(jarray array),- $(jsize i)) } |]--setObjectArrayElement :: Coercible o (J a) => JObjectArray -> Int32 -> o -> IO ()-setObjectArrayElement array i (coerce -> upcast -> x) = withJNIEnv $ \env ->- [C.exp| void {- (*$(JNIEnv *env))->SetObjectArrayElement($(JNIEnv *env),- $(jobjectArray array),- $(jsize i),- $(jobject x)); } |]
src/Foreign/JNI/Types.hs view
@@ -38,6 +38,7 @@ , JMethodID(..) , JFieldID(..) , JValue(..)+ , withJValues -- * JNI defined object types , JObject , JClass@@ -63,7 +64,7 @@ import Data.ByteString.Builder (Builder) import Data.Char (chr, ord) import Data.Int-import Data.Map (fromList)+import qualified Data.Map as Map import Data.Monoid ((<>)) import Data.Singletons ( Sing@@ -74,16 +75,23 @@ #endif ) import Data.Singletons.TypeLits (KnownSymbol, symbolVal)-import Data.String (fromString) import Data.Word import Foreign.C (CChar)+import Foreign.ForeignPtr+ ( ForeignPtr+ , castForeignPtr+ , newForeignPtr_+ , withForeignPtr+ ) import Foreign.JNI.NativeMethod import qualified Foreign.JNI.String as JNI+import Foreign.Marshal.Alloc (allocaBytesAligned) import Foreign.Ptr import Foreign.Storable (Storable(..)) import GHC.TypeLits (Symbol) import Language.C.Types (TypeSpecifier(TypeName))-import Language.C.Inline.Context (Context(..))+import Language.C.Inline.Context (Context(..), fptrCtx)+import System.IO.Unsafe (unsafePerformIO) -- | A JVM instance. newtype JVM = JVM_ (Ptr JVM)@@ -122,9 +130,9 @@ instance IsReferenceType ty => IsReferenceType ('Generic ty tys) data instance Sing (a :: JType) where- SClass :: JNI.String -> Sing ('Class sym)- SIface :: JNI.String -> Sing ('Iface sym)- SPrim :: JNI.String -> Sing ('Prim sym)+ SClass :: String -> Sing ('Class sym)+ SIface :: String -> Sing ('Iface sym)+ SPrim :: String -> Sing ('Prim sym) SArray :: Sing ty -> Sing ('Array ty) SGeneric :: Sing ty -> Sing tys -> Sing ('Generic ty tys) SVoid :: Sing 'Void@@ -132,11 +140,11 @@ -- XXX SingI constraint temporary hack because GHC 7.10 has trouble inferring -- this constraint in 'signature'. instance (KnownSymbol sym, SingI sym) => SingI ('Class (sym :: Symbol)) where- sing = SClass $ fromString $ symbolVal (undefined :: proxy sym)+ sing = SClass $ symbolVal (undefined :: proxy sym) instance (KnownSymbol sym, SingI sym) => SingI ('Iface (sym :: Symbol)) where- sing = SIface $ fromString $ symbolVal (undefined :: proxy sym)+ sing = SIface $ symbolVal (undefined :: proxy sym) instance (KnownSymbol sym, SingI sym) => SingI ('Prim (sym :: Symbol)) where- sing = SPrim $ fromString $ symbolVal (undefined :: proxy sym)+ sing = SPrim $ symbolVal (undefined :: proxy sym) instance SingI ty => SingI ('Array ty) where sing = SArray sing instance (SingI ty, SingI tys) => SingI ('Generic ty tys) where@@ -148,14 +156,14 @@ type a <> g = 'Generic a g -- | Type indexed Java Objects.-newtype J (a :: JType) = J (Ptr (J a))- deriving (Eq, Show, Storable)+newtype J (a :: JType) = J (ForeignPtr (J a))+ deriving (Eq, Show) type role J representational -- | The null reference. jnull :: J a-jnull = J nullPtr+jnull = J $ unsafePerformIO $ newForeignPtr_ nullPtr -- | Any object can be cast to @Object@. upcast :: J a -> JObject@@ -163,7 +171,7 @@ -- | Unsafe type cast. Should only be used to downcast. unsafeCast :: J a -> J b-unsafeCast (J x) = J (castPtr x)+unsafeCast (J x) = J (castForeignPtr x) -- | Parameterize the type of an object, making its type a /generic type/. generic :: J a -> J (a <> g)@@ -205,25 +213,42 @@ (JLong x) == (JLong y) = x == y (JFloat x) == (JFloat y) = x == y (JDouble x) == (JDouble y) = x == y- (JObject (J x)) == (JObject (J y)) = castPtr x == castPtr y+ (JObject (J x)) == (JObject (J y)) = castForeignPtr x == castForeignPtr y _ == _ = False -instance Storable JValue where- sizeOf _ = 8- alignment _ = 8+sizeOfJValue, alignmentJValue :: Int+sizeOfJValue = 8+alignmentJValue = 8 - poke p (JBoolean x) = poke (castPtr p) x- poke p (JByte x) = poke (castPtr p) x- poke p (JChar x) = poke (castPtr p) x- poke p (JShort x) = poke (castPtr p) x- poke p (JInt x) = poke (castPtr p) x- poke p (JLong x) = poke (castPtr p) x- poke p (JFloat x) = poke (castPtr p) x- poke p (JDouble x) = poke (castPtr p) x- poke p (JObject x) = poke (castPtr p :: Ptr (J a)) x+-- | @withJValue jvalues f@ provides a pointer to an array containing the given+-- @jvalues@.+--+-- The array is valid only while evaluating @f@.+withJValues :: [JValue] -> (Ptr JValue -> IO a) -> IO a+withJValues args f =+ allocaBytesAligned (sizeOfJValue * length args) alignmentJValue $ \p ->+ foldr (.) id (zipWith (withJValueOff p) [0..] args) (f p) - peek _ = error "Storable JValue: undefined peek"+-- @withJValueOff p n jvalue io@ writes the given @jvalue@ to @p `plusPtr` n@+-- and runs @io@.+--+-- The jvalue is guaranteed to stay valid while @io@ evaluates.+withJValueOff :: Ptr JValue -> Int -> JValue -> IO a -> IO a+withJValueOff p n jvalue io = case jvalue of+ JBoolean x -> pokeByteOff (castPtr p) offset x >> io+ JByte x -> pokeByteOff (castPtr p) offset x >> io+ JChar x -> pokeByteOff (castPtr p) offset x >> io+ JShort x -> pokeByteOff (castPtr p) offset x >> io+ JInt x -> pokeByteOff (castPtr p) offset x >> io+ JLong x -> pokeByteOff (castPtr p) offset x >> io+ JFloat x -> pokeByteOff (castPtr p) offset x >> io+ JDouble x -> pokeByteOff (castPtr p) offset x >> io + JObject (J x) -> withForeignPtr x $ \xp ->+ pokeByteOff (castPtr p) offset xp >> io+ where+ offset = n * sizeOfJValue+ -- | Get the Java type of a value. #if MIN_VERSION_singletons(2,2,0) jtypeOf :: JValue -> SomeSing JType@@ -257,9 +282,10 @@ referenceTypeName (SGeneric ty@(SIface _) _) = referenceTypeName ty referenceTypeName _ = error "referenceTypeName: Impossible." -classSymbolBuilder :: JNI.String -> Builder+classSymbolBuilder :: String -> Builder classSymbolBuilder sym =- Prim.primMapByteStringFixed (subst Prim.>$< Prim.word8) (JNI.toByteString sym)+ Prim.primMapByteStringFixed (subst Prim.>$< Prim.word8)+ (JNI.toByteString $ JNI.fromChars sym) where subst (chr . fromIntegral -> '.') = fromIntegral (ord '/') subst x = x@@ -275,7 +301,7 @@ signatureBuilder (SPrim "long") = Builder.char7 'J' signatureBuilder (SPrim "float") = Builder.char7 'F' signatureBuilder (SPrim "double") = Builder.char7 'D'-signatureBuilder (SPrim sym) = error $ "Unknown primitive: " ++ show sym+signatureBuilder (SPrim sym) = error $ "Unknown primitive: " ++ sym signatureBuilder (SArray ty) = Builder.char7 '[' <> signatureBuilder ty signatureBuilder (SGeneric ty _) = signatureBuilder ty signatureBuilder SVoid = Builder.char7 'V'@@ -317,7 +343,7 @@ type JDoubleArray = JArray ('Prim "double") jniCtx :: Context-jniCtx = mempty { ctxTypesTable = fromList tytab }+jniCtx = mempty { ctxTypesTable = Map.fromList tytab } <> fptrCtx where tytab = [ -- Primitive types@@ -330,20 +356,20 @@ , (TypeName "jfloat", [t| Float |]) , (TypeName "jdouble", [t| Double |]) -- Reference types- , (TypeName "jobject", [t| JObject |])- , (TypeName "jclass", [t| JClass |])- , (TypeName "jstring", [t| JString |])- , (TypeName "jarray", [t| JObject |])- , (TypeName "jobjectArray", [t| JObjectArray |])- , (TypeName "jbooleanArray", [t| JBooleanArray |])- , (TypeName "jbyteArray", [t| JByteArray |])- , (TypeName "jcharArray", [t| JCharArray |])- , (TypeName "jshortArray", [t| JShortArray |])- , (TypeName "jintArray", [t| JIntArray |])- , (TypeName "jlongArray", [t| JLongArray |])- , (TypeName "jfloatArray", [t| JFloatArray |])- , (TypeName "jdoubleArray", [t| JDoubleArray |])- , (TypeName "jthrowable", [t| JThrowable |])+ , (TypeName "jobject", [t| Ptr JObject |])+ , (TypeName "jclass", [t| Ptr JClass |])+ , (TypeName "jstring", [t| Ptr JString |])+ , (TypeName "jarray", [t| Ptr JObject |])+ , (TypeName "jobjectArray", [t| Ptr JObjectArray |])+ , (TypeName "jbooleanArray", [t| Ptr JBooleanArray |])+ , (TypeName "jbyteArray", [t| Ptr JByteArray |])+ , (TypeName "jcharArray", [t| Ptr JCharArray |])+ , (TypeName "jshortArray", [t| Ptr JShortArray |])+ , (TypeName "jintArray", [t| Ptr JIntArray |])+ , (TypeName "jlongArray", [t| Ptr JLongArray |])+ , (TypeName "jfloatArray", [t| Ptr JFloatArray |])+ , (TypeName "jdoubleArray", [t| Ptr JDoubleArray |])+ , (TypeName "jthrowable", [t| Ptr JThrowable |]) -- Internal types , (TypeName "JavaVM", [t| JVM |]) , (TypeName "JNIEnv", [t| JNIEnv |])