获取有效的JNIEnv指针 我有一个C++ DLL,我想在Unity中使用,通过将函数导出到C。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 }

获取有效的JNIEnv指针 我有一个C++ DLL,我想在Unity中使用,通过将函数导出到C。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 },java,android,unity3d,dll,java-native-interface,Java,Android,Unity3d,Dll,Java Native Interface,在Unity中,我有以下导出的Dll函数 [DllImport (dllName)] private static extern void api_initialize (IntPtr java_env, IntPtr app_context, IntPtr class_loader); 我的问题是如何在C#类中获取JNIEnv指针,然后将其作为参数传递到此函数中? 我不是这个API的创建者,也没有修改它的权限,所以我需要从JNIEnv获取JavaVM,而不是相反 我想你没有办

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

    [DllImport (dllName)]
    private static extern void api_initialize (IntPtr java_env, IntPtr app_context, IntPtr class_loader);
我的问题是如何在C#类中获取JNIEnv指针,然后将其作为参数传递到此函数中?


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

我想你没有办法做到这一点(可能在那里,但还没有看到)因为这种类型的
NDK调用
需要java包装,所以我想使用另一种解决方案,使用java作为C#调用的
中间
,然后您可以
将此调用从
java
重定向到
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<AndroidJavaObject>("obj");
    return plugin.Call("javaCallToNDK");
  } 
}
#endif
当您声明本机方法时,
javah
会自动生成一个ndk调用定义,并将javaEnv和jobject作为参数,因此我想您只需要在这里传递类加载器。您可以尝试此方法,并链接case以获得更多说明


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

我认为你可以创建另一个本机插件,它将为你提供JNIEnv

总结本文,您应该尝试以下内容(未经测试的伪代码):

然后在C中#


扩展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++中传递JNIZENV或JVM变量。

我相信您可以在这里找到答案->或者使用Oracle文档创建您的自定义java调用->ationhttp://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp715 无论如何,这是一个很好的问题。你能用JNI_GetCreatedJavaVMs用于此?我认为只有当Java模块显式请求加载库(System.loadLibrary)时才会调用JNI_OnLoad。这很有帮助,而且很有效!我与执行部门进行了确认。
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;
}
[DllImport ("PluginName")]
private static extern IntPtr GetJniEnv();
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;
}