From: Ustulation <ust...@gm...> - 2017-10-05 21:41:19
|
Hey, I have successfully got to invoking async C code i wrote from Java. This is how the C header looks like: *// native C header: will call the given function pointer from a diffent thread (async) void backend_with_string(void *ctx, void(*o_cb)(void *ctx, const char *result)); * For this I manually created my jni interface source file: * // jni source code static void backend_with_string_jni_cb(void *user_data, const char *result) { JniContextAsync *ctx = (JniContextAsync*)user_data; JNIEnv *new_env; (*ctx->vm)->AttachCurrentThread(ctx->vm, (void**)&new_env, 0); jstring java_result = (*new_env)->NewStringUTF(new_env, result); (*new_env)->ExceptionClear(new_env); (*new_env)->CallVoidMethod(new_env, ctx->obj, ctx->cb_method_id, java_result); (*new_env)->DeleteGlobalRef(new_env, ctx->obj); (*ctx->vm)->DetachCurrentThread(ctx->vm); free(ctx); } JNIEXPORT void JNICALL Java_Frontend_BackendWithStringJNI( JNIEnv *env, jobject obj, jstring cb_name ) { const char *cb_name_cstr = (*env)->GetStringUTFChars(env, cb_name, 0); jclass obj_class = (*env)->GetObjectClass(env, obj); jmethodID cb_method_id = (*env)->GetMethodID( env, obj_class, cb_name_cstr, "(Ljava/lang/String;)V"); (*env)->ReleaseStringUTFChars(env, cb_name, cb_name_cstr); // Assume this is just a C struct with 3 member variables as below JniContextAsync *jni_ctx = (JniContextAsync*)malloc(sizeof(JniContextAsync)); (*env)->GetJavaVM(env, &jni_ctx->vm); jni_ctx->obj = (*env)->NewGlobalRef(env, obj); jni_ctx->cb_method_id = cb_method_id; backend_with_string(jni_ctx, backend_with_string_async_jni_cb); }* and finally the Java source file: *// java Frontend.java source file class Frontend { private native void BackendWithStringJNI(String cb_name); public void backend_with_string_cb(String result) { System.out.println("- Got in the Java callback: " + result); } public void backend_with_string() { BackendWithStringJNI("backend_with_string_cb"); } public static void main(String args[]) { Frontend obj = new Frontend(); obj.backend_with_string(); System.out.println("- Control returned back in Java"); } static { System.loadLibrary("frontend"); } }* I think it's a pretty standard paradigm where the async C backend takes a void* as and argument which it will pass back to the callback on as-is basis for the caller to retain their context. The callback is called in C thread (not Java main thread) so the jni intermediary callback I defined above does all that standard *AttachCurrentThread()* etc. Then finally *backend_with_string_cb* in Java is called. This is of-course called in C thread so somehow the result needs to be posted in the main Java thread, but that's impl detail for later (and doable with mutexes. condition vars etc - I'm not a Java dev so just taking a guess here). I have Frontend code in Java, Objective-C, NodeJS so far which i need to cater to. Was just wondering if SWIG could help me here ? I did get SWIG to work with normal blocking API function calls but no clue how to get async-callbacks like above to work. Can you guys please help me here or provide me pointers as to if this is possible with SWIG and how people go about it ? Thanks -- Sent from: http://swig.10945.n7.nabble.com/swig-user-f3.html |