获取有效的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 }
在Unity中,我有以下导出的Dll函数获取有效的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,而不是相反 我想你没有办
[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;
}