转自: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

 

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <dlfcn.h>
  5. #include <jni.h>
  6. char * GetStringA(void)
  7. {
  8. return"i am in a.so";
  9. }
  10. jstring Java_com_ckl_SoCallSo_SoCallSoActivity_fucntionInA(JNIEnv* env, jobject thiz)
  11. {
  12. return (*env)->NewStringUTF(env, GetStringA());
  13. }
  14. jstring Java_com_ckl_SoCallSo_SoCallSoActivity_AcallB(JNIEnv* env, jobject thiz)
  15. {
  16. jstring ret;
  17. //so路径:/data/data/我的程序的包名/lib/我的so文件名
  18. void * filehandle = dlopen("/data/data/com.ckl.SoCallSo/lib/libb.so", RTLD_LAZY );
  19. if (filehandle)
  20. {
  21. char * ( * funcPtrB)(void) = NULL;
  22. funcPtrB = dlsym(filehandle, "GetStringB");
  23. if (funcPtrB)
  24. {
  25. ret = (*env)->NewStringUTF(env, funcPtrB());
  26. }
  27. else
  28. {
  29. ret = (*env)->NewStringUTF(env, "dlsym GetStringB failed!");
  30. }
  31. dlclose(filehandle);
  32. }
  33. else
  34. {
  35. ret = (*env)->NewStringUTF(env, "dlopen failed!");
  36. }
  37. return ret;
  38. }

b.c

 

 

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <dlfcn.h>
  5. #include <jni.h>
  6. char * GetStringB(void)
  7. {
  8. return"i am in b.so";
  9. }
  10. jstring Java_com_ckl_SoCallSo_SoCallSoActivity_fucntionInB(JNIEnv* env, jobject thiz)
  11. {
  12. return (*env)->NewStringUTF(env, GetStringB());
  13. }
  14. jstring Java_com_ckl_SoCallSo_SoCallSoActivity_BcallA(JNIEnv* env, jobject thiz)
  15. {
  16. jstring ret;
  17. //so路径:/data/data/我的程序的包名/lib/我的so文件名
  18. void * filehandle = dlopen("/data/data/com.ckl.SoCallSo/lib/liba.so", RTLD_LAZY );
  19. if (filehandle)
  20. {
  21. char * ( * funcPtrA)(void) = NULL;
  22. funcPtrA = dlsym(filehandle, "GetStringA");
  23. if (funcPtrA)
  24. {
  25. ret = (*env)->NewStringUTF(env, funcPtrA());
  26. }
  27. else
  28. {
  29. ret = (*env)->NewStringUTF(env, "dlsym GetStringA failed!");
  30. }
  31. dlclose(filehandle);
  32. }
  33. else
  34. {
  35. ret = (*env)->NewStringUTF(env, "dlopen failed!");
  36. }
  37. return ret;
  38. }

Android.mk

 

 

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE := a
  4. LOCAL_SRC_FILES := a.c
  5. include $(BUILD_SHARED_LIBRARY)
  6. include $(CLEAR_VARS)
  7. LOCAL_MODULE := b
  8. LOCAL_SRC_FILES := b.c
  9. include $(BUILD_SHARED_LIBRARY)

 

a.c、b.c分别生成liba.so、libb.so,liba.so要调用libb.so中的GetStringB()函数,libb.so要调用liba.so中的GetStringA()函数。


 

另外,so文件的路径为 /data/data/我的程序的包名/lib/我的so文件名。

工程源码 SoCallSo.7z

运行效果如下:

posted on 2012-03-10 15:34  且听风止  阅读(1677)  评论(0编辑  收藏  举报