使用dlopen()而不是system.loadlib的Android JNI

使用dlopen()而不是system.loadlib的Android JNI,android,c,android-ndk,java-native-interface,dlopen,Android,C,Android Ndk,Java Native Interface,Dlopen,我可以使用System.loadLibrary(lib)在android java中加载我的共享库并使用它。目前这种方法的问题是,我实际上可以运行两个android应用程序实例 如果我的应用程序有两个实例和一个共享库,那就不行了。我需要两个共享库的实例。好消息是,从java中,我可以发现我运行的是实例A还是实例B;这样做一开始就把事情搞砸了 到目前为止,我所做的是找出我正在运行的实例,并将其传递给JNI,然后在.c文件中加载。因此,使用dlopen,现在我有了一个共享库的句柄 java方面:

我可以使用
System.loadLibrary(lib)在android java中加载我的共享库并使用它。目前这种方法的问题是,我实际上可以运行两个android应用程序实例

如果我的应用程序有两个实例和一个共享库,那就不行了。我需要两个共享库的实例。好消息是,从java中,我可以发现我运行的是实例A还是实例B;这样做一开始就把事情搞砸了

到目前为止,我所做的是找出我正在运行的实例,并将其传递给JNI,然后在.c文件中加载。因此,使用dlopen,现在我有了一个共享库的句柄

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");
    }

}
我有两个问题,引导我提出这个想法的最初帖子使用了这样一个函数原型:

dlmopen(LM_ID_NEWLM, "path/to/lib", RTLD_NOW | RTLD_LOCAL);
在android上,使用
LM_ID_NEWLM
编译会抛出一个
LM_ID_NEWLM
未声明的(此函数首次使用)

因此,我尝试使用基于本地的RTLD_

我目前在编译此项目时没有收到任何错误



我现在的问题是,一旦从c代码加载了这些库,我实际上如何使用它们呢?

不,如果不使用
System.loadLibrary()
或等效工具,就不能使用JNI。

不,如果不使用
System.loadLibrary()
或等效工具,就不能使用JNI。

如果(lib==0)
?这不应该是
if(mainHandle==NULL)
或者
if(sdlHandle==NULL)
?加载两次会有帮助吗?Per:“如果使用dlopen()再次加载相同的共享对象,则返回相同的对象句柄。”在粘贴某些代码时,libe==0是一种类型。根据您提供的标记RTLD_LOCAL的链接,“此共享对象中定义的符号不可用于解析随后加载的共享对象中的引用。”这基本上将共享库视为静态每次调用,除非我弄错了,我可能是。我还不清楚你想实现什么。如果有两个应用程序实例在单独的进程中运行,则它们都可以加载相同的库,并且不会相互干扰。直接使用
dlopen()。您是否试图在一个进程中拥有同一共享库的两个不同副本?如果是的话。。。为什么?它是一个设计很差的库,有很多全局变量吗?我想为同一应用程序的两个实例提供两个不同的共享库副本。这不是同一个进程,但是如果一个进程已经加载,那么另一个进程就会打开,访问这些lib,这会造成很多麻烦。只需在两个单独的进程中打开同一个库就不会造成任何麻烦。系统中的每个进程都打开了各种库(例如libc)。出现问题的唯一方法是,如果库需要以独占方式访问某些全局资源,那么使用dlopen()玩什么游戏都无关紧要。
if(lib==0)
?这不应该是
if(mainHandle==NULL)
或者
if(sdlHandle==NULL)
?加载两次会有帮助吗?Per:“如果使用dlopen()再次加载相同的共享对象,则返回相同的对象句柄。”在粘贴某些代码时,libe==0是一种类型。根据您提供的标记RTLD_LOCAL的链接,“此共享对象中定义的符号不可用于解析随后加载的共享对象中的引用。”这基本上将共享库视为静态每次调用,除非我弄错了,我可能是。我还不清楚你想实现什么。如果有两个应用程序实例在单独的进程中运行,则它们都可以加载相同的库,并且不会相互干扰。直接使用
dlopen()。您是否试图在一个进程中拥有同一共享库的两个不同副本?如果是的话。。。为什么?它是一个设计很差的库,有很多全局变量吗?我想为同一应用程序的两个实例提供两个不同的共享库副本。这不是同一个进程,但是如果一个进程已经加载,那么另一个进程就会打开,访问这些lib,这会造成很多麻烦。只需在两个单独的进程中打开同一个库就不会造成任何麻烦。系统中的每个进程都打开了各种库(例如libc)。出现问题的唯一方法是,如果库要求以独占方式访问某些全局资源,在这种情况下,使用dlopen()玩什么游戏无关紧要。是否可以编写加载程序库,请使用system.loadlibrary加载该库;然后基于java中的一些运行时变量,使用该库来执行dlopen,并且在运行时可能有两个所需库的实例?是的,这是可能的。您正在寻找一种方法来保持一些全局变量分离?它们可能会彼此模糊是的,因为它们是两个不同的进程,所以应该有一种方法来加载。这样它们就不会碰撞。我现在正在加载一个包装库,然后编写一些代码来创建两个句柄,这两个句柄用这个命令打开:dlopen(“/data/app lib/app.name/libWantedLib.so”,RTLD_now);我不确定这是否与调用system.loadlibrary()相同,我希望在这条路走得太远而最终到达我开始的地方之前获得一些见解。不仅如此,androids dlopen()似乎不支持那么多标志。如果在两个独立的库中使用一个库,那么您不必担心:每个库都可以使用
System.load()
ldopen()
加载它自己的库,并与另一个库完全隔离。另一方面
RTLD\u组
不是