您的位置:首页 > 移动开发 > Android开发

Android JNI helloworld程序编写与编译-图文解说

2012-02-02 09:55 351 查看
这是一个经典的helloworld程序,此程序本身并没有什么功能,但是其意义在于抛砖引玉。了解了JNI的机理,对于那些习惯于C程序的人很重要,在处理底层的读写等操作就可以在UI层用java轻而易举地实现,就

如同C程序中调用一个系统调用那么简单,下面分步叙述。

一、创建最上层的java程序
首先打开eclipse,创建一个java工程,并在工程中添加一个类,类名为helloworld.java,如图所示:



2011-5-22 19:35:19 上传
下载附件
(221.97 KB)

打开java源码helloworld.java,编写代码,实现c语言中的printf功能,代码如下:



2011-5-22 19:38:04 上传
下载附件
(642.01 KB)

Print()函数的声明中,关键字native标明此方法是一个“本地”方法或者“原生”方法,即从c/c++库中调用的方法。
Main()函数必须为static,否则运行时会报错,找不到main,原因不详。
Static段中的loadLibrary提供了此程序运行时需要加载的c动态链接库***.so,print()的实现就在此库中。

二、

编译helloworld.java
编译helloworld.java的方法有两种,一种是在shell中利用javac编译,另一种在eclipse中,直接保存。
对于第一种方法,直接告诉javac编译器需要编译的文件即可,命令如下:

Javac helloworld.java
生成的helloworld.class就在$(shell pwd)下。
第二种方法,eclipse会在工程目录下的bin目录下生成helloworld.class。

三、

生成JNI头文件helloworld.h
利用javah命令生成。Javah的命令格式如下:
javah –jni –classpath <classpath> <classfile>
例如我的helloworld.class文件是由eclipse生成的,因此其绝对路径是:

/root/Project/jni/helloworld/bin/helloworld.class
我当前所在目录为/root/Project/jni/helloworld/
上面的命令就可以写成:javah –jni –classpath bin helloworld
命令执行后再$(shell pwd)下生成一个文件:helloworld.h,其内容如下:



2011-5-22 19:42:38 上传
下载附件
(1.1 MB)

在这个文件中提供了java到c的接口

JNIEXPORT void JNICALL Java_helloworld_print(JNIEnv *, jobject);
另外,jni.h中定义了各种从java到c的类型转换,宏定义等。
接着我在工程根目录下创建了一个目录include,将生成的头文件mv到include目录下。

四、

创建helloworld.c并编译生成动态链接库helloworld.so
首先编写代码如下(推荐在vim或者其他可视化编辑软件中):



2011-5-22 19:45:42 上传
下载附件
(435.81 KB)

由图中可见,此处就是最上层的helloworld.java代码中的方法的实现,在此实现中没有用到系统提供的两个参数,但是此2个参数非常重要。第一个参数代表此共享库运行的环境,即java虚拟机,在虚拟机中奖上层的java类型转换为C类型。第二个参数类似于C++中的this对象,C代码要通过此函数来改变对象中某些变量的值。
接下来要做的就是将此C代码编译成共享链接库文件,可以直接在shell里完成,或者为了便于管理,通过GNU
make。
编译时需要定位jni.h所在路径,locate,结果如下:



2011-5-22 19:47:39 上传
下载附件
(829.83 KB)

由于我当前使用的ndk是~/Project/android-ndk-r4b,并且我想让程序运行在宿主机上,于是选择第4条或者第6条,我选第6条,因此在gcc的flags里应该添加此路径。
为了方便起见,我在helloworld根目录下创建一个makefile,采用递归调用Makefile,深入到各目录中进行操作,对各子目录下的Makefile统一管理:



2011-5-22 19:49:22 上传
下载附件
(796.71 KB)

源文件所在目录的Makefile如下:



2011-5-22 19:52:03 上传
下载附件
(1.3 MB)

使用make命令在工程根目录下编译之后,在工程根目录下的lib目录中生产了helloworld.so的共享库文件:



2011-5-22 19:54:47 上传
下载附件
(107.05 KB)

五、

检验程序正确性
运行程序有两个方法:shell中运行和eclipse中运行。
1.

shell中运行
运行jni程序需要告诉java两个参数,即classpath和共享库的位置。
classpath可以通过设置环境变量:
export CLASSPATH=$CLASSPATH:/root/Project/workspace/jni/helloworld/bin/
而共享库的位置在命令行中给出即可:

Java –Djava.library.path=’lib/’ helloworld
运行结果如下:



2011-5-22 19:55:51 上传
下载附件
(124.69 KB)

2.

eclipse中运行
需要为java虚拟机设置共享库路径,打开run configurations,切换到第二个选项卡arguments,在虚拟机参数输入框中输入
-Djava.library.path=/root/Project/workspace/jni/helloworld/lib/
如图所示:



2011-5-22 19:58:12 上传
下载附件
(1.47 MB)

之后运行,运行结果如下:



2011-5-22 19:59:22 上传
下载附件
(1.47 MB)

六、
补充说明

我的工程根目录:/root/Project/workspace/jni/helloworld/
如果用eclipse编写代码并运行的话,需要为eclipse安装CDT插件,这样才可以支持c/c++。对于这个程序,如果不使用eclipse,可能反而更简单一些。
另外,环境变量的设置也很重要,要根据自己系统中jdk的路径设置环境变量,设置方法可以上网搜索。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐