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的專欄”