Android NDK编译C/C++为so共享对象

来源:互联网 发布:人力资源管理专业知乎 编辑:程序博客网 时间:2024/05/29 04:32

概念

JNI(Java Native Interface,Java本地接口),实现了Java和其他语言的交互(主要是C/C++),如:Java程序通过JNI调用C/C++编写的在Windows上运行的DLL动态链接库。

so(shared object,共享对象),Linux系统中的动态库,类似于Windows系统中的DLL。.so有时被直接调用,有时会参与到编译中。Android由Linux内核发展而来,因此在Android系统中也使用.so。

Android NDK(Android Native Development Kit),是Google提供的一系列的工具,简化通过JNI将C/C++动态库编译为.so库的过程。NDK集成了交叉编译器,并提供了相应的.mk文件隔离CPU、平台、ABI等差异,开发者只需要简单修改mk文件,执行编译脚本就可以创建.so。

NDK与JNI的关系:

JNI是Java与其他语言交互的机制,是Java语言自身的特性,与Android无关。

Android在框架上分为Application应用层、Application Framework应用框架层、libraries类库、Linux kernel内核。在应用框架层以及之上,使用Java语言进行开发;在此之下,Android自身的类库、驱动使用C/C++编写,再通过JNI提供接口给上层的Java调用。所以,Android框架使用了大量的JNI技术,让应用层的开发人员使用Java操控C/C++。

通常的Android开发都在应用框架层以及之上进行,但有时也需要对底层进行实现。显然,对底层的开发要复杂得多,NDK则是Google推出的帮助开发者通过C/C++编写应用的开发包,包含部分Android底层中常用的C/C++的头文件、库文件、说明文档和示例代码。

安装

Windows下配置NDK的步骤:
1、下载:android-ndk-r13b-windows-x86_64.zip
2、解压:D:\sdk\android-ndk-r13b
3、环境变量:

ANDROID_NDK:D:\sdk\android-ndk-r13b PATH:%ANDROID_NDK%

4、验证:cmd命令输入ndk-build若出现“Android NDK: Could not find application project directory”表示NDK正确安装,只是没有待编译的工程而已。

NDK中的hello-jni

可以下载Google的NDK Samples,下面以其中的hello-jni工程为例,说明NDK中JNI的使用:

hello-jni工程目录结构:

  • hello-jni
    • jni
      • Android.mk(编译配置文件)
      • hello-jni.c(.c代码)
    • res
    • src
      • com/example/hellojni/HelloJni.java(.java代码)
    • test

ndk-build

JNI是独立于NDK存在的,了解JNI才对NDK有更好的认识。[参考1]。

独立使用JNI时,需要自行使用Cygwin等编译工具将C/C++代码编译为动态库;而NDKr7开始,集成了交叉编译器和ndk-build.cmd脚本,开发者可以直接执行这个脚本完成编译工作。

运行以下命令,进行编译:

D:\>cd sdk\android-ndk-r13b\samples\hello-jni    //定位到hello-jniD:\sdk\android-ndk-r13b\samples\hello-jni>ndk-build    //编译

P.S.
当ndk-build命令提示找不到工程时,可以查看工程的Android.mk文件中的路径关系,定位到正确的路径后使用ndk-build命令。或者,可以将工程路径设置为NDK_PROJECT_PATH环境变量。

编译成功的话,\hello-jni会多出两个文件夹\libs与\obj。其中:
\libs目录下是编译出来的不同CPU类型的.so文件,在实际使用时根据需要选择
\obj是编译过程中的生成的其他文件(如.o中间文件,或调试文件)
这里写图片描述

调用

在Eclipse-ADT中import进hello-jni工程,建立与\src同级的文件夹\libs,并把编译出来的.so放在该文件夹下。(这里我直接import进编译后的工程文件夹)
这里写图片描述

直接运行出结果:
这里写图片描述

Android.mk

ndk-build命令实际是执行了%NDK_PROJECT_PATH%/jni/Android.mk这个makefile文件,如果未配置%NDK_PROJECT_PATH%环境变量,则需要定位到工程目录。同时,待编译的.c和编译配置文件Android.mk也需要位于名为jni的目录下。

Android.mk是NDK编译的配置文件,其中定义了需要编译的.c文件、依赖的.h头文件、编译出的so库名等等信息,是使用NDK进行编译的关键。

//Android.mkLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := hello-jni    //编译出的库名为 libhello-jni.soLOCAL_SRC_FILES := hello-jni.c  //编译源文件include $(BUILD_SHARED_LIBRARY)

Android.mk常见配置

常见配置将在工作中积累更新…

Application.mk

不同CPU编译的.so不同,ndk-build默认编译所有CPU的.so。可以通过Application.mk文件指定APP_ABI指定CPU,如armeabi-v7a。

//Application.mkAPP_ABI := all  //编译所有CPU的.soAPP_ABI := armeabi-v7a  //编译armeabi-v7a的.so

Eclipse集成NDK编译操作

前文中对NDK的操作都使用cmd命令,显然在工作中十分不便,好在可以将这些操作都集成到Eclipse中的按钮,一键完成任务。
参考:Eclipse集成JNI与AndroidNDK操作

Eclipse添加NDK携带的JNI代码提示

NDK中携带了不同CPU的JNI操作源码,可以添加到Eclipse中有助于在Eclipse中编写JNI的C/C++代码。

1、右击工程 -> Android Tools -> Add Native Support,之后点击弹出窗口的finish即可
2、右击工程 -> Properties -> C/C++ General -> Paths and Symbols,选择c,cpp语言 -> Add,使用File system选择NDK中一个Android版本具体CPU实现的include,确定即可。

//include路径D:\sdk\android-ndk-r13b\platforms\android-19\arch-arm\usr\include

这里写图片描述

提示效果:
这里写图片描述

参考

  1. JNI入门——hellojni
  2. so格式文件是什么
  3. Android jni开发资料–NDK环境搭建
  4. Android框架介绍
  5. NDK与JNI的关系
  6. Eclipse集成JNI与AndroidNDK操作
1 0