获取有效的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,而不是相反。

  • 线程优先安全性exception请确保apk已经签名
  • Unity Android构建错误WIN32exceptionZipAlign
  • Android - 在活动中embeddedUnity3d场景 - 需要注销接收器?
  • Android UnityPlayerActivity动作栏
  • Unity中的回调监听器 - 如何从Android中的UnityPlayerActivity调用脚本文件方法
  • 在Tango AR摄像机中的遮挡
  • 适用于iOS和Android的Unity3D:多人游戏(蓝牙连接)
  • 实现Parse Unity插件的应用程序在Android设备上崩溃,但在编辑器中工作正常
  • 我想你无法做到这一点(可能在那里,但还没有看到它)因为这种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。