我有一个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指针,然后将其作为参数传递给这个函数?
我不是这个接口的创建者,也没有修改它的权限,所以我需要从JNIEnv获取JavaVM,而不是相反。
发布于 2016-08-13 22:46:21
我猜你没有办法做到这一点(可能已经有了,但还没有见过),因为这种类型的NDK calls需要java包装,所以我想要另一个解决方案,它使用Java作为C#调用的intermediate,然后你可以从java redirect这个调用到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在您的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调用定义,所以我猜你只需要在这里传递类加载器,.You可以尝试这个link和this链接,以获得更多的解释。
Good Luck.Hope这会有帮助的。
发布于 2016-08-18 05:59:08
我认为你可以创建另一个原生插件,它将为你提供JNIEnv。
总结这篇文章,你应该尝试这样的东西(未经测试的伪代码):
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();发布于 2018-04-21 02:30:54
在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;
}JNI_OnLoad由Unity/Java自动调用
不需要C#,因为您可以在c++中传递jni_env或JVM变量。
https://stackoverflow.com/questions/38862197
复制相似问题