2015-09-25 107 views
0

我可以使用System.loadLibrary(lib);在android java中加載我的共享庫並使用它。目前這種方法的問題是我實際上可以運行兩個我的android應用程序的實例。使用dlopen()代替system.loadlib的Android JNI

讓我的應用程序有兩個實例與一個共享庫不一樣。我需要共享庫的兩個實例。好的新功能是,從java中我可以發現是否運行實例A或實例B.有時我會在實例A中運行,但仍然必須加載實例B;這樣做完全混淆了第一例。

我到目前爲止所做的是找出我正在運行哪個實例,然後將其傳遞給JNI,然後在我的.c文件中加載.so與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_LOCAL上this question

我編譯這個項目時,目前沒有得到任何錯誤。

我現在的問題是,如何從c代碼中加載這些庫文件?

+0

'if(lib == 0)'?不應該是'if(mainHandle == NULL)'或'if(sdlHandle == NULL)'嗎?並會加載兩次幫助?根據http://man7.org/linux/man-pages/man3/dlopen.3.html:「如果使用dlopen()再次加載相同的共享對象,則返回相同的對象句柄。」 –

+0

libe == 0是我粘貼一些代碼時的一種類型。根據您提供的標誌RTLD_LOCAL的鏈接「在此共享的 對象中定義的符號不可用於解決隨後加載的共享對象中的引用。」 「。它基本上把共享庫視爲一個靜態的每個調用,除非我錯了,我可能是這樣。 – user1610950

+0

目前還不清楚你想要完成什麼。如果有兩個應用程序實例在不同的進程中運行,它們都可以加載相同的庫並且不會互相干擾。直接使用'dlopen()'並沒有什麼不同於'loadLibrary()'。你是否試圖在同一個進程中擁有同一共享庫*的兩個不同副本*?如果是這樣......爲什麼?這是一個設計不佳的圖書館,裏面有很多全球性的圖書館嗎? – fadden

回答

0

不,如果您不使用System.loadLibrary()或同等效果,則不能使用JNI。

+0

是否可以編寫一個加載程序庫,使用system.loadlibrary加載它;那麼基於來自java的一些運行時變量使用該lib來執行dlopen並且在運行時可能有兩個所需庫的實例? – user1610950

+0

是的,這是可能的。你正在尋找一種方法來保持一些全局變量的獨立性?它們可能會彼此模糊 –

+0

是的,因爲它們是兩個截然不同的進程,所以應該有一種方法來加載.so以便它們不會相互衝突。我正在加載一個包裝庫,然後編寫一些代碼來創建兩個句柄,這些句柄用這個命令打開:dlopen(「/ data/app-lib/app.name/libWantedLib.so」,RTLD_NOW);我不確定這是否與調用system.loadlibrary()相同,並且我希望在沿着這條路徑走得太遠之前獲得一些洞察力,直到結束於我開始的地方。不僅如此,似乎androids dlopen()不支持這麼多標誌。 – user1610950