频道栏目
首页 > 程序开发 > 移动开发 > Android > 正文
android的ndk下,解决两个so相互调用的问题
2011-09-30 13:34:44           
收藏   我要投稿

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的专栏”
 

点击复制链接 与好友分享!回本站首页
相关TAG标签 两个 问题
上一篇:Android应用程序消息处理机制(Looper、Handler)分析
下一篇:Android开发中,退出键功能及menu不能使用的问题
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站