获取有效的JNIEnv指针

我有一个C ++ DLL,我想通过将函数导出到C#来在Unity中使用。 Unity项目在Android设备上运行,C ++代码使用java。 要初始化C ++,我需要先调用以下函数:

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

在Unity中,我有以下导出的Dll函数

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

我的问题是如何在我的C#类中获取JNIEnv指针然后作为parameter passing给此函数?

我不是这个API的创建者,也没有修改它的权限,所以我需要从JNIEnv获取JavaVM,而不是相反。

我想你无法做到这一点(可能在那里,但还没有看到它)因为这种types的NDK calls需要java环绕所以我想用另一个解决方案,使用Java作为你的C#的intermediate调用,然后您可以将此调用redirectjava NDK code

 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 

并在您的java文件中执行此操作

 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()); } } 

当你声明本机方法时, javah自动生成一个带有javaEnv和jobject作为参数的ndk调用定义,所以我猜你只需要在这里传递类加载器。你可以尝试这个链接和这个链接,以便进一步澄清。

祝你好运。希望这会有所帮助。

我想你可以创建另一个本机插件,它会给你JNIEnv。

适用于Android的插件

总结这篇文章你应该尝试这样的事情(未经测试的伪代码)

 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; } 

然后在C#

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

扩展Vyacheslav Gerasimov的答案,此代码经过测试并无需任何额外工作即可完成:

 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; } 

Unity / Java会自动调用JNI_OnLoad

不需要C#,因为您可以在c ++中传递jni_env或JVMvariables。