轉自:http://blog.csdn.net/victoryckl/article/details/6832333
A、B兩個模組,主要都是用C實現的,需要用ndk編譯成兩個a.so、b.so,但是a.so內調用b.so中的函數,b.so內也調用了a.so中的函數,而且由於某些原因A、B必須分開編譯。問題是無論先編譯那個模組都會編譯不通過,因為它們相互依賴。
為了編譯通過,必須在編譯時間取消這種依賴關係,下面程式中使用dlopen開啟so,dlsym擷取函數指標,就避免了這種編譯依賴關係。
a.c
[cpp] view plaincopyprint?
- #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;
- }
#include <stdio.h><br />#include <stdlib.h><br />#include <stdarg.h><br />#include <dlfcn.h><br />#include <jni.h></p><p>char * GetStringA(void)<br />{<br />return "i am in a.so";<br />}</p><p>jstring Java_com_ckl_SoCallSo_SoCallSoActivity_fucntionInA(JNIEnv* env, jobject thiz)<br />{<br />return (*env)->NewStringUTF(env, GetStringA());<br />}</p><p>jstring Java_com_ckl_SoCallSo_SoCallSoActivity_AcallB(JNIEnv* env, jobject thiz)<br />{<br />jstring ret;<br />//so路徑:/data/data/我的程式的包名/lib/我的so檔案名稱<br />void * filehandle = dlopen("/data/data/com.ckl.SoCallSo/lib/libb.so", RTLD_LAZY );<br />if (filehandle)<br />{<br />char * ( * funcPtrB)(void) = NULL;<br />funcPtrB = dlsym(filehandle, "GetStringB");<br />if (funcPtrB)<br />{<br />ret = (*env)->NewStringUTF(env, funcPtrB());<br />}<br />else<br />{<br />ret = (*env)->NewStringUTF(env, "dlsym GetStringB failed!");<br />}<br />dlclose(filehandle);<br />}<br />else<br />{<br />ret = (*env)->NewStringUTF(env, "dlopen failed!");<br />}</p><p>return ret;<br />}<br />
b.c
[cpp] view plaincopyprint?
- #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;
- }
#include <stdio.h><br />#include <stdlib.h><br />#include <stdarg.h><br />#include <dlfcn.h><br />#include <jni.h></p><p>char * GetStringB(void)<br />{<br />return "i am in b.so";<br />}</p><p>jstring Java_com_ckl_SoCallSo_SoCallSoActivity_fucntionInB(JNIEnv* env, jobject thiz)<br />{<br />return (*env)->NewStringUTF(env, GetStringB());<br />}</p><p>jstring Java_com_ckl_SoCallSo_SoCallSoActivity_BcallA(JNIEnv* env, jobject thiz)<br />{<br />jstring ret;<br />//so路徑:/data/data/我的程式的包名/lib/我的so檔案名稱<br />void * filehandle = dlopen("/data/data/com.ckl.SoCallSo/lib/liba.so", RTLD_LAZY );<br />if (filehandle)<br />{<br />char * ( * funcPtrA)(void) = NULL;<br />funcPtrA = dlsym(filehandle, "GetStringA");<br />if (funcPtrA)<br />{<br />ret = (*env)->NewStringUTF(env, funcPtrA());<br />}<br />else<br />{<br />ret = (*env)->NewStringUTF(env, "dlsym GetStringA failed!");<br />}<br />dlclose(filehandle);<br />}<br />else<br />{<br />ret = (*env)->NewStringUTF(env, "dlopen failed!");<br />}<br />return ret;<br />}
Android.mk
[cpp] view plaincopyprint?
- 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)
LOCAL_PATH := $(call my-dir)</p><p>include $(CLEAR_VARS)<br />LOCAL_MODULE := a<br />LOCAL_SRC_FILES := a.c<br />include $(BUILD_SHARED_LIBRARY)</p><p>include $(CLEAR_VARS)<br />LOCAL_MODULE := b<br />LOCAL_SRC_FILES := b.c<br />include $(BUILD_SHARED_LIBRARY)
a.c、b.c分別產生liba.so、libb.so,liba.so要調用libb.so中的GetStringB()函數,libb.so要調用liba.so中的GetStringA()函數。
[cpp] view plaincopyprint?
另外,so檔案的路徑為 /data/data/我的程式的包名/lib/我的so檔案名稱。
工程源碼 SoCallSo.7z
運行效果如下: