C++调用JNI常见套路
在OnLoad的时候把env保存下来,然后getEnv的时候使用AttachCurrentThread。需要注意的是:每个进程都有自己的JNIEnv对象,不能把JNIEnv作为全局变量保存下来,可以把JavaVM这个对象保存下来。
当开发者通过JNI_OnLoad的方式加载so的时候,JNI_OnLoad才会被调用。如果开发者直接把env传了进来,则也能够通过env把JavaVM保存下来。
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
//将vm对象保存下来
return JNI_VERSION_1_6;
}
JNIEnv*getEnv(){
JNIEnv* jni_env = 0;
vm->AttachCurrentThread(&jni_env, 0);
}
通过env获取JavaVM
SYMBOL_HIDDEN void initGlobalData(JNIEnv *env) {
auto g = getGlobalData();
if (g->Vm == nullptr) {
env->GetJavaVM(&(g->Vm));
}
}
传递activity给C++层
AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"); var requestId = CLIB.ppf_InitializeAndroidAsynchronous(appId, activity.GetRawObject(), IntPtr.Zero);
动态库
如果一个so使用了JNI_ON_LOAD
那么加载它的时候,必须使用java的system.loadlibrary加载这个动态链接库,而不能直接使用C++去加载它。JVM虚拟机加载了一个动态链接库,跟C++加载了一个动态链接库,不一样。
在Unity里面使用JVM显式加载一个库。
//AndroidJavaObject system = new AndroidJavaClass("java.lang.System");
// system.CallStatic("loadLibrary", "volcenginertc");
//system.CallStatic("loadLibrary", "byteaudio");
Unity报错:找不到dll
-
首先检查dll的属性,是否勾选了android armv7或者armv8等。
-
检查apk里面是否有dll,如果没有,说明动态链接库压根没有打包进去
-
Unity在加载A.dll的过程中,如果发生错误,则直接报A.dll不存在;因此,找不到dll的原因可能是加载dll的时候报错了。
-
在JNI_OnLoad等处判断是否有抛出异常
-
A.dll是否依赖了另一个dll,如果另一个dll缺失,则A.dll加载失败。
-
Unity调C++时无法传递JNIEnv
https://stackoverflow.com/questions/38862197/getting-valid-jnienv-pointer
只能在C++侧使用JNI_Onload来实现获取JVM。
unity导入package含有dylib
设置/安全与隐私/通用,设置允许xxx。