android ndk 动态库_百度经验,android ndk 动态库

android ndk开发经常遇到了动态库的问题,本文主要介绍:

① 动态链接库的生成;

② 在Java和C混合编程的情况下如何调用第三方动态链接库;

③ 通过jar包的方式间接调用第三方动态链接库;

④ 使用dlopen程序运行时直接调用;

⑤ 纯c的方式开发调用;

本文重点推荐②和⑤,第④中太麻烦每个函数都需要dlsym调用一次,第③中主要用在有第三方jar包的情况下;

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

代码的百度云链接:http://pan.baidu.com/s/1dD3qkQ9 密码:c5s3

工具/原料

Win7 x64

adt-bundle-windows-x86_64-20140702

android-ndk-r10

生成动态库

1

android ndk下面生成动态库so文件的方法很多,但是这里只提供一种方法,更多的生成方法可以看,“ndk 编译静态库”:

http://jingyan.baidu.com/article/63f236280b90690208ab3d12.html

2

fkAdd.c 的内容如下:

#include

int fkAdd(int nX, int nY)

{

returnnX + nY;

}

3

Android.mk 的内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE:= fkAdd

LOCAL_SRC_FILES:= fkAdd.c

include $(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)

{

returnnX + nY;

}

12

临时修改 Android.mk 文件内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#LOCAL_MODULE := hello-jni

#LOCAL_SRC_FILES := hello-jni.c

LOCAL_MODULE := fkaddso

LOCAL_SRC_FILES := fkAdd.c

include $(BUILD_SHARED_LIBRARY)

13

使用快捷键Ctrl+B编译后可以在libs目录下面看到生成的一些列的

libfkaddso.so文件,如下图所示

END

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 := fkaddso

LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := hello-jni

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SHARED_LIBRARIES := fkaddso

include $(BUILD_SHARED_LIBRARY)

4

修改 HelloJni.java 在其中增加一行:

System.loadLibrary("fkaddso");

5

运行工程看效果:

END

用jar调用so

1

菜单->File->New->Android Application Project

2

创建一个没有主题的android project

3

1、取消复选框 Create activity

2、选择复选框 Mark this project as a library

3、Next

4

点击 Next

5

点击 Finish

6

新建一个类: NativeSo,包名:fuke.nativeso

7

在 NativeSo.java 中添加如下内容:

package fuke.nativeso;

package fuke.nativeso;

public class NativeSo {

static {

System.loadLibrary("fkaddso");

System.loadLibrary("nativeso");

}

public static native int GetTestValue();

}

8

1、右键工程->Anroid Tools->Add Native Support

2、将 生成动态库 部分生成的jni目录下面的: libs目录,Android.mk,Application.mk 三个文件拷贝到本工程的jni目录下面

3、修改 Android.mk中的内容为:

LOCAL_PATH := $(call my-dir)

### 把动态链接库重新名一个模块名

include $(CLEAR_VARS)

LOCAL_MODULE := fkaddso

LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := nativeso

LOCAL_SRC_FILES := NativeSo.c

LOCAL_SHARED_LIBRARIES := fkaddso

include $(BUILD_SHARED_LIBRARY)

9

通过javah生成 fuke_nativeso_NativeSo.h,关于如何利用javah生成native方法对应的头文件,见“ndk java 和 c 互掉”:

http://jingyan.baidu.com/article/f54ae2fcde72be1e92b84916.html

10

在 NativeSo.c 文件中添加内容:

#include

#include "fuke_nativeso_NativeSo.h"

extern int fkAdd(int nX, int nY);

JNIEXPORT jint JNICALL Java_fuke_nativeso_NativeSo_GetTestValue

(JNIEnv *pJniEnv, jclass pJclass){

returnfkAdd(100, 1000);

}

11

Application.mk 中内容如下:

APP_ABI := all

12

按照 生成动态库部分中的1-10这10个步骤导入ndk测试用例 HelloJni

13

1、右键工程属性

2、选择android分页

3、增加 NativeSo 库

4、点击Apply

5、点击OK

14

修改 HelloJni.java 文件的方法 onCreate:

tv.setText( stringFromJNI() + NativeSo.GetTestValue());

15

编译运行后效果如下:

16

在 HelloJni.java 中增加:

System.loadLibrary("fkaddso");

System.loadLibrary("nativeso");

删除 NativeSo.java 中删除对应的几行:

17

为了方便验证修改下过,修改 NativeSo.c 中的数据:

returnfkAdd(100, 999);

18

编译运行后的效果如下:

END

用dlopen调用so

1

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

2

把需要调用so文件的目录libs拷贝到jni目录下面,并修改 Android.mk 文件的内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := fkaddso

LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := hello-jni

LOCAL_SRC_FILES := hello-jni.c

include $(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

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

END

纯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 := fkAdd

LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkAdd.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := main

LOCAL_SRC_FILES := main.c

LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM

LOCAL_STATIC_LIBRARIES := android_native_app_glue

LOCAL_SHARED_LIBRARIES := fkAdd

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := native-activity

LOCAL_SRC_FILES := NativeActivity.c

LOCAL_LDLIBS := -llog -landroid

LOCAL_STATIC_LIBRARIES := android_native_app_glue

include $(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 效果如下:

END

注意事项

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值