diff --git a/src/main/java/org/bytedeco/javacpp/tools/Generator.java b/src/main/java/org/bytedeco/javacpp/tools/Generator.java index 9488e7be9..9a64ade0f 100644 --- a/src/main/java/org/bytedeco/javacpp/tools/Generator.java +++ b/src/main/java/org/bytedeco/javacpp/tools/Generator.java @@ -280,6 +280,7 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver out.println(); out.println("#ifdef __ANDROID__"); out.println(" #include "); + out.println(" #include "); out.println("#elif defined(__APPLE__) && defined(__OBJC__)"); out.println(" #include "); out.println(" #include "); @@ -466,6 +467,20 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver out.println(" va_end(ap);"); out.println("}"); out.println(); + out.println("#ifdef __ANDROID__"); + out.println(" static pthread_key_t current_env;"); + out.println(" static JavaCPP_noinline void JavaCPP_detach_env(void *data)"); + out.println(" {"); + out.println(" if (JavaCPP_vm) {"); + out.println(" JavaCPP_vm->DetachCurrentThread();"); + out.println(" }"); + out.println(" }"); + out.println(" static JavaCPP_noinline void JavaCPP_create_pthread_key(void)"); + out.println(" {"); + out.println(" pthread_key_create(¤t_env, JavaCPP_detach_env);"); + out.println(" }"); + out.println("#endif"); + out.println(); if (baseLoadSuffix == null || baseLoadSuffix.isEmpty()) { out.println("static inline jboolean JavaCPP_trimMemory() {"); out.println("#if defined(__linux__) && !defined(__ANDROID__)"); @@ -1156,8 +1171,11 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver out.println(); } if (!functions.isEmpty() || !virtualFunctions.isEmpty()) { + out.println("static pthread_once_t once = PTHREAD_ONCE_INIT;"); + out.println("static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;"); + out.println(); out.println("static JavaCPP_noinline void JavaCPP_detach(bool detach) {"); - out.println("#ifndef NO_JNI_DETACH_THREAD"); + out.println("#if !defined(NO_JNI_DETACH_THREAD) && !defined(__ANDROID__)"); out.println(" if (detach && JavaCPP_vm->DetachCurrentThread() != JNI_OK) {"); out.println(" JavaCPP_log(\"Could not detach the JavaVM from the current thread.\");"); out.println(" }"); @@ -1188,6 +1206,14 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver out.println("#endif"); } out.println(" }"); + out.println("#ifdef __ANDROID__"); + out.println(" pthread_mutex_lock(&lock);"); + out.println(" pthread_once(&once, JavaCPP_create_pthread_key);"); + out.println(" if ((*env = (JNIEnv *)pthread_getspecific(current_env)) != NULL) {"); + out.println(" attached = true;"); + out.println(" goto done;"); + out.println(" }"); + out.println("#endif"); out.println(" if (vm->GetEnv((void**)env, " + JNI_VERSION + ") != JNI_OK) {"); out.println(" struct {"); out.println(" JNIEnv **env;"); @@ -1197,17 +1223,24 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver out.println(" if (vm->AttachCurrentThread(env2, NULL) != JNI_OK) {"); out.println(" JavaCPP_log(\"Could not attach the JavaVM to the current thread.\");"); out.println(" *env = NULL;"); - out.println(" return false;"); + out.println(" goto done;"); out.println(" }"); + out.println("#ifdef __ANDROID__"); + out.println(" pthread_setspecific(current_env, *env);"); + out.println("#endif"); out.println(" attached = true;"); out.println(" }"); out.println(" if (JavaCPP_vm == NULL) {"); out.println(" if (JNI_OnLoad" + loadSuffix + "(vm, NULL) < 0) {"); out.println(" JavaCPP_detach(attached);"); out.println(" *env = NULL;"); - out.println(" return false;"); + out.println(" goto done;"); out.println(" }"); out.println(" }"); + out.println("done:"); + out.println("#ifdef __ANDROID__"); + out.println(" pthread_mutex_unlock(&lock);"); + out.println("#endif"); out.println(" return attached;"); out.println("}"); out.println();