Obtenir un pointeur JNIEnv valide

J’ai une dll C ++ que je veux utiliser dans Unity en exportant les fonctions en C #. Le projet Unity s’exécute sur des appareils Android et le code C ++ utilise Java. Pour initialiser le C ++, je dois d’abord appeler la fonction suivante:

void api_initialize(JNIEnv* env, jobject* app_context, jobject* class_loader) { JavaVM* vm = nullptr; env->GetJavaVM(&vm); if (!vm) { return; } //Do other proprietary things } 

Dans Unity, j’ai la fonction Dll exscope suivante

  [DllImport (dllName)] private static extern void api_initialize (IntPtr java_env, IntPtr app_context, IntPtr class_loader); 

Ma question est Comment puis-je obtenir un pointeur JNIEnv dans ma classe C # à passer ensuite en tant que paramètre dans cette fonction?

Je ne suis pas le créateur de cette API et je ne dispose pas de l’access nécessaire pour la modifier. Je dois donc obtenir le JavaVM de JNIEnv, et non l’inverse.

Je suppose qu’il est impossible de le faire (peut-être mais vous ne l’avez pas encore vu), car ce type d’ NDK calls java, je voudrais donc proposer une autre solution utilisant Java comme intermediate pour votre C #. Vous pouvez ensuite redirect cet appel vers le NDK code depuis java .

 using UnityEngine; using System.Collections; using System.IO; #if UNITY_ANDROID public class JavaCallPlugin { // Avoid invalid calls public static void initiateNDK() { if (Application.platform != RuntimePlatform.Android) return; var pluginClass = new AndroidJavaClass("com.package.class.UnityJavaDelegate"); AndroidJavaObject plugin = pluginClass.CallStatic("obj"); return plugin.Call("javaCallToNDK"); } } #endif 

Et dans votre fichier java, faites ceci

 package com.package.class; import android.content.ContentValues; import android.content.Intent; import android.os.Environment; public class UnityJavaDelegate{ private static UnityJavaDelegate obj; // define function call to your NDK method with native keyword private native void api_initialize(); static { System.loadLibrary("yourlibraryname"); // setup your ndk lib to use } public static UnityJavaDelegate getObj() { if(m_instance == null) obj= new UnityJavaDelegate(); return obj; } private UnityJavaDelegate(){ } public void javaCallToNDK(){ // this call may not work because i haven't passed class // loader TO NDK before, if not then you should try links // at the bottom of the post to know how to pass customize // as parameter to NDK. // put your call to NDK function here api_initialize(this.getClass().getClassLoader()); } } 

Lorsque vous déclarez une méthode native, javah génère automatiquement une définition d’appel ndk avec javaEnv et jobject en tant que paramètre. Par conséquent, il suffit de passer le chargeur de classes ici. Vous pouvez essayer ce lien et ce lien au cas où davantage d’éclaircissements soient apportés.

Good Luck.Hope Cela aidera.

Je pense que vous pouvez créer un autre plugin natif qui vous donnera JNIEnv.

Plugins pour Android

En résumant cet article, vous devriez essayer quelque chose comme ceci (pseudo-code non testé) :

 JavaVM* g_JVM; // JavaVM is valid for all threads, so just save it globally extern "C" { JNIEnv* GetJniEnv(); } // The VM calls JNI_OnLoad when the native library is loaded jint JNI_OnLoad(JavaVM* vm, void* reserved) { g_JVM = vm; return JNI_VERSION_1_6; } // The JNI interface pointer (JNIEnv) is valid only in the current thread. JNIEnv* GetJniEnv() { JNIEnv* jni_env = 0; g_JVM->AttachCurrentThread(&jni_env, 0); return jni_env; } 

Puis en C #

 [DllImport ("PluginName")] private static extern IntPtr GetJniEnv(); 

En développant la réponse de Vyacheslav Gerasimov, ce code est testé et dissortingbué sans aucun travail supplémentaire requirejs:

 JNIEnv* jni_env = NULL; JavaVM* JVM; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JVM = vm; if (vm->GetEnv((void**)&jni_env, JNI_VERSION_1_6) != JNI_OK) __android_log_print(ANDROID_LOG_ERROR, "Unity", "ERROR: GetEnv failed") return JNI_VERSION_1_6; } 

JNI_OnLoad est appelé automatiquement par Unity / Java

Aucun C # n’est requirejs car vous pouvez transmettre votre variable jni_env ou JVM en c ++.