您的位置:首页 > 产品设计 > UI/UE

使用ndk-build编译 android调用的so库

2014-05-08 22:33 399 查看

前沿

编译so的方法有两种方法第一种就是编写原生的makefile文件利用gcc进行编译,这里我讲解的是另外一种。采用NDK提供的ndk-build编译。

简介

使用ndk编译的时候需要介绍它的脚本文件,Android.mk和Application.mk,但是Application.mk是可选的,用来描述原生程序用到的一些特性,如原生程序支持的ARM指令集。
Android.mk是工程的编译脚本,描述了编译原生程序所需要的选择项、头文件、源文件以及依赖库等。

实例

首先需要下载DNK,这个就不用多说了,我直接来说步骤吧。程序员一般都会对Hello,world感到亲切,我们就从hello,word开始。利用eclipse新建一个项目我取了新建了一个andoridNDKTest这个项目,先看看项目目录吧。


 

这里注意到上面的多了一个jni目录,这个目录就是java通过jni调用的代码放的地方,里面放了三个文件,我们还是首先来讲一下hell-jni.c这个文件,我们来看看代码。
#include <string.h>
#include <jni.h>
jstring
Java_com_example_ndktest_MainActivity_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello world ");
}
代码很简单就是命名有点长,第一个Java不用管就是jni的规定,然后后面的就是包路径和类名称最后是函数名。这个函数的作用就是返回一个字符串。

然后就是利用ndk来编译这个函数了,我们需要看看Android.mk和Applicaion.mk文件里面到底有些什么。
android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH:=($call my-dir)定义了本地源码路径 call my-dir是编译系统提供的,返回的就是mk的路径。
include $(CLEAR_VARS) 指定让编译系统清楚掉一些已经定义过的宏,这些宏定义都是全局的,如LOCAL_MODULE、LOCAL_SRC_FILE,当一个GUN MAKE在编译多个模块时候,必须清楚并且重新设置他们。
LOCAL_ARM_MODE := arm指定原生程序用的指令集,这里上面我们没有用到。
LOCAL_MODULE:= hello指定生成程序的文件名,如果生成共享的库模块会生成libhello.so.
LOCAL_SRC_FILE:=hello-jni.c指定c或者c++源文件。
inlude $(BUILD_EXECUTABLE)指定生成文件的类型,BUILD_EXECUTABLE表示可执行文件,BUILD_SHARED_LIBRARY表示生成动态库,BUILD_STATIC_LIBRARY静态库。
然后是Applicaion.mk文件
APP_ABI := all
这句代码的意思是生成所有平台的编译结果。
其实到了这里你就可以直接进入jni文件夹里面输入ndk-build开始编译了,但是为了看到编译过后的运行结果我这里在eclipse里面编译,看图说话。







然后编译器就会自动的编译文件,最后就是android这边的调用了,我们来看看andorid的文件代码
public class MainActivity extends Activity {

//声明c的接口
public native String stringFromJNI();

static {
System.loadLibrary("hello");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TextView textView = (TextView) findViewById(R.id.hello);
textView.setText(stringFromJNI());
}
}


然后让我们注意的是 这句代码
public native String stringFromJNI();

其实它就是函数生命,但是采用的native因为是在so里面的。
static {
System.loadLibrary("hello");
}
这句函数就更简单了,直接加载我们刚才编译好的so库。好了,如果没什么问题就直接run在手机上看效果吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息