多语言展示
当前在线:1387今日阅读:183今日分享:19

android ndk 动态库

android ndk开发经常遇到了动态库的问题,本文主要介绍:      ① 动态链接库的生成;      ② 在Java和C混合编程的情况下如何调用第三方动态链接库;      ③ 使用dlopen程序运行时直接调用;      ④ 纯c的方式开发调用;      本文重点推荐②和④,第③中太麻烦每个函数都需要dlsym调用一次;      代码的百度云链接: http://pan.baidu.com/s/1dD3qkQ9 密码:c5s3
工具/原料
1

Win8.1 x64

2

adt-bundle-windows-x86_64-20140702

3

android-ndk-r10d

生成动态库
1

android ndk下面生成动态库so文件的方法很多,但是这里只提供一种方法,更多的生成方法可以看,“ndk 编译静态库”:http://jingyan.baidu.com/article/63f236280b90690208ab3d12.html

2

fkAdd.c 的内容如下:#include int fkAdd(int nX, int nY){      return nX + nY;}

3

Android.mk 的内容如下:LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE:= fkAddLOCAL_SRC_FILES:= fkAdd.cinclude $(BUILD_SHRRED_LIBRARY)

4

1、打开 eclipse 2、点击 文件3、点击 新建4、点击 other...

5

1、展开 Android 选项;2、选择 Android Project from Existing Code;3、点击 Next

6

1、输入 Root Director;2、取消 tests;3、选中 Copy projects into workspace;4、点击 Finish;

7

1、右键工程;2、选择 Android Tools;3、Add Native Support...;

8

点击 Finish

9

修改android sdk 版本为 4.0.3;关于如何修改 android sdk 版本:http://jingyan.baidu.com/article/c910274bfdd000cd371d2d4b.html

10

修改 Min SDK version:15修改 Target SDK version:19

11

在jni目录下面新建文件fkAdd.c 的内容如下:int fkAdd(int nX, int nY){      return nX + nY;}

12

临时修改 Android.mk 文件内容如下:LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)#LOCAL_MODULE    := hello-jni#LOCAL_SRC_FILES := hello-jni.cLOCAL_MODULE    := fkaddsoLOCAL_SRC_FILES := fkAdd.cinclude $(BUILD_SHARED_LIBRARY)

13

使用快捷键Ctrl+B编译后可以在libs目录下面看到生成的一些列的libfkaddso.so文件,如下图所示

Java和c编程调so
1

1、将libs复制一份到jni目录下面,删掉其中不相关的文件2、删掉文件 jni/fkadd.c 文件3、将 Android.mk 文件还原成最开始的样子;

2

修改 hello-jni.c 中的部分代码,如下:char szMsg[1024] = {0}; int nSum = fkAdd(100, 10); sprintf (szMsg, 'Hello from JNI !  Compiled with ABI ' ABI '. %d ',  nSum); return (*env)->NewStringUTF(env, szMsg);

3

修改 Android.mk 文件:LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := fkaddsoLOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE    := hello-jniLOCAL_SRC_FILES := hello-jni.cLOCAL_SHARED_LIBRARIES := fkaddsoinclude $(BUILD_SHARED_LIBRARY)

4

修改 HelloJni.java 在其中增加一行:System.loadLibrary('fkaddso');

5

运行工程看效果:

用dlopen调用so
1

重复“生成动态库”中的过程1到10,

2

把需要调用so文件的目录libs拷贝到jni目录下面,并修改 Android.mk 文件的内容如下:LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := fkaddsoLOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE    := hello-jniLOCAL_SRC_FILES := hello-jni.cinclude $(BUILD_SHARED_LIBRARY)

3

修改 hello-jni.c 的内容如下:char* szSo = '/data/data/com.example.hellojni/lib/libfkaddso.so'; void* fkAddSo = dlopen(szSo, RTLD_LAZY); int (*fpAdd)(int,int) =  (int (*)(int,int))dlsym(fkAddSo, 'fkAdd'); char szMsg[1024] = {0}; int nSum = fpAdd(100, 200); dlclose(fkAddSo); sprintf (szMsg, '%s %d', szSo, nSum); return (*env)->NewStringUTF(env, szMsg);

4

关于如何获取 so在手机中的路径,可以通过在控制台下输入 adb shell 后,在手机上查询:

5

编译后运行效果:

6

方便他人亦是方便自己,如果觉得还行就点下下边的投票吧,这样可以帮助其他人更快的找到解决问题的方法;有疑问的也可留言哦, 谢谢!

纯c的方式开发调用
1

此方法需要感谢ndk吧的吧友提供哦,本人只是负责将其进行了整理,归纳后发帖,谢谢,原始地址:http://tieba.baidu.com/p/3247530080

2

根据“生成动态库”中的过程1到10,新建一个纯c的ndk程序:“D:\Android\android-ndk-r10\samples\native-activity'

3

把会用的so文件的目录libs拷贝到 jni目录下面

4

修改 Android.mk 文件,内容如下:LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := fkAddLOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkAdd.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE    := mainLOCAL_SRC_FILES := main.cLOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CMLOCAL_STATIC_LIBRARIES := android_native_app_glueLOCAL_SHARED_LIBRARIES := fkAddinclude $(BUILD_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE    := native-activityLOCAL_SRC_FILES := NativeActivity.cLOCAL_LDLIBS    := -llog -landroidLOCAL_STATIC_LIBRARIES := android_native_app_glueinclude $(BUILD_SHARED_LIBRARY)$(call import-module,android/native_app_glue)

5

增加 NativeActivity.c 文件,添加内容如下:#include #include #include #include void android_main(struct android_app* state) {    // Make sure glue isn't stripped.    app_dummy();    void* soAdd = dlopen('/data/data/com.example.native_activity/lib/libfkAdd.so',RTLD_NOW);    void* soMain = dlopen('/data/data/com.example.native_activity/lib/libmain.so',RTLD_NOW);    void (*fp_android_main)(struct android_app*) =    (void (*)(struct android_app*))dlsym(soMain,'android_main');    fp_android_main(state);    dlclose(soMain);    dlclose(soAdd);}

6

在 main.c 文件中添加一行,方便测试:__android_log_print(ANDROID_LOG_DEBUG, 'fuke', 'engine_handle_input 100 + 200 = [%d] ', fkAdd(100, 200));

7

编译运行,点击手机屏幕后,观察logcat 效果如下:

注意事项

c++的函数在写动态链接库的时候,需要注意的是c++的函数会被系统修改,所以做动态库测试的使用最好用c语言

推荐信息