我可以使用System.loadLibrary(lib);
在 android java 中加载我的共享库并使用它。当前方法的问题是我实际上可以运行两个 Android 应用程序实例。
我的应用程序有两个实例和一个共享库则不然。我需要共享库的两个实例。好消息是,我可以从 java 中找出我正在运行实例 A 还是实例 B。有时我会在实例 A 中运行,但仍然必须加载实例 B;有时我会在实例 A 中运行,但仍然必须加载实例 B;这样做完全搞乱了第一个实例。
到目前为止我所做的就是找出我正在运行的实例并将其传递给 JNI,然后在我的 .c 文件中我使用 dlopen 加载 .so,现在我有了我的共享库的句柄。
Java 端:
if(preview)
{
for (String lib : getLibraries()) {
nativeInitPreview(lib);
}
}
else
{
for (String lib : getLibraries()) {
nativeInitLive(lib);
}
}
C 代码端:
static void *mainHandleLive = NULL;
static void *SDLHandleLive = NULL;
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeInitLive(JNIEnv* env, jobject instance, jstring lib)
{
const char *libString = (*env)->GetStringUTFChars(env, lib, NULL);
__android_log_print(ANDROID_LOG_INFO, "SDL", "Java_org_libsdl_app_SDLActivity_nativeInitLive %s", libString);
(*env)->ReleaseStringUTFChars(env, lib, libString);
mainHandleLive = dlopen("/data/app-lib/org.libsdl.app-1/libmain.so", RTLD_NOW | RTLD_LOCAL);
if (mainHandleLive == 0)
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "/data/app-lib/org.libsdl.app-1/libmain.so failed to open");
}
SDLHandleLive = dlopen("/data/app-lib/org.libsdl.app-1/libSDL2.so", RTLD_NOW | RTLD_LOCAL);
if (SDLHandleLive == 0)
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "/data/app-lib/org.libsdl.app-1/libSDL2.so failed to open");
}
}
我有两个问题,引导我想到这个想法的最初帖子使用了这样的函数原型(prototype):
dlmopen(LM_ID_NEWLM, "path/to/lib", RTLD_NOW | RTLD_LOCAL);
在 android 上使用 LM_ID_NEWLM
进行编译抛出 LM_ID_NEWLM
未声明(在此函数中首次使用)。
所以我尝试使用基于this question的RTLD_LOCAL
目前我在编译此项目时没有遇到任何错误。
我现在的问题是,从 C 代码加载这些库后,我如何实际使用它们?
最佳答案
不,如果您不使用 System.loadLibrary()
或等效函数,则无法使用 JNI。
关于Android JNI 使用 dlopen() 代替 system.loadlib,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32778853/