android的ndk下,解決兩個so相互調用的問題

來源:互聯網
上載者:User

A、B兩個模組,主要都是用C實現的,需要用ndk編譯成兩個a.so、b.so,但是a.so內調用b.so中的函數,b.so內也調用了a.so中的函數,而且由於某些原因A、B必須分開編譯。問題是無論先編譯那個模組都會編譯不通過,因為它們相互依賴。

為了編譯通過,必須在編譯時間取消這種依賴關係,下面程式中使用dlopen開啟so,dlsym擷取函數指標,就避免了這種編譯依賴關係。

a.c

view plain
#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include <dlfcn.h> 
#include <jni.h> 
 
char * GetStringA(void) 

    return "i am in a.so"; 

 
jstring Java_com_ckl_SoCallSo_SoCallSoActivity_fucntionInA(JNIEnv* env, jobject thiz) 

    return (*env)->NewStringUTF(env, GetStringA()); 

 
jstring Java_com_ckl_SoCallSo_SoCallSoActivity_AcallB(JNIEnv* env, jobject thiz) 

    jstring ret; 
    //so路徑:/data/data/我的程式的包名/lib/我的so檔案名稱 
    void *  filehandle = dlopen("/data/data/com.ckl.SoCallSo/lib/libb.so", RTLD_LAZY ); 
    if (filehandle) 
    { 
        char * ( * funcPtrB)(void) = NULL; 
        funcPtrB = dlsym(filehandle, "GetStringB"); 
        if (funcPtrB) 
        { 
            ret = (*env)->NewStringUTF(env, funcPtrB()); 
        } 
        else 
        { 
            ret = (*env)->NewStringUTF(env, "dlsym GetStringB failed!"); 
        } 
        dlclose(filehandle); 
    } 
    else 
    { 
        ret = (*env)->NewStringUTF(env, "dlopen failed!"); 
    } 
 
    return ret; 

b.c
view plain
#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include <dlfcn.h> 
#include <jni.h> 
 
char * GetStringB(void) 

    return "i am in b.so"; 

 
jstring Java_com_ckl_SoCallSo_SoCallSoActivity_fucntionInB(JNIEnv* env, jobject thiz) 

    return (*env)->NewStringUTF(env, GetStringB()); 

 
jstring Java_com_ckl_SoCallSo_SoCallSoActivity_BcallA(JNIEnv* env, jobject thiz) 

    jstring ret; 
    //so路徑:/data/data/我的程式的包名/lib/我的so檔案名稱 
    void *  filehandle = dlopen("/data/data/com.ckl.SoCallSo/lib/liba.so", RTLD_LAZY ); 
    if (filehandle) 
    { 
        char * ( * funcPtrA)(void) = NULL; 
        funcPtrA = dlsym(filehandle, "GetStringA"); 
        if (funcPtrA) 
        { 
            ret = (*env)->NewStringUTF(env, funcPtrA()); 
        } 
        else 
        { 
            ret = (*env)->NewStringUTF(env, "dlsym GetStringA failed!"); 
        } 
        dlclose(filehandle); 
    } 
    else 
    { 
        ret = (*env)->NewStringUTF(env, "dlopen failed!"); 
    } 
    return ret; 

Android.mk
view plain
LOCAL_PATH := $(call my-dir) 
 
include $(CLEAR_VARS) 
LOCAL_MODULE := a 
LOCAL_SRC_FILES := a.c 
include $(BUILD_SHARED_LIBRARY) 
 
include $(CLEAR_VARS) 
LOCAL_MODULE := b 
LOCAL_SRC_FILES := b.c 
include $(BUILD_SHARED_LIBRARY) 
a.c、b.c分別產生liba.so、libb.so,liba.so要調用libb.so中的GetStringB()函數,libb.so要調用liba.so中的GetStringA()函數。

view plain
 
另外,so檔案的路徑為 /data/data/我的程式的包名/lib/我的so檔案名稱。

工程源碼 SoCallSo.7z

運行效果如下:

作者“victoryckl的專欄”
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.