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

 

这是一个经典的helloworld程序,此程序本身并没有什么功能,但是其意义在于抛砖引玉。了解了JNI的机理,对于那些习惯于C程序的人很重要,在处理底层的读写等操作就可以在UI层用java轻而易举地实现,就
如同
C程序中调用一个系统调用那么简单,下面分步叙述。


一、创建最上层的java程序

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

1.bmp

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

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

2.bmp

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

Print()函数的声明中,关键字native标明此方法是一个“本地”方法或者“原生”方法,即从c/c++库中调用的方法。

Main()函数必须为static,否则运行时会报错,找不到main,原因不详。

Static段中的loadLibrary提供了此程序运行时需要加载的c动态链接库***.soprint()的实现就在此库中。


二、
编译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,其内容如下: 3.bmp

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

在这个文件中提供了javac的接口


JNIEXPORT void JNICALL Java_helloworld_print(JNIEnv *, jobject);

另外,jni.h中定义了各种从javac的类型转换,宏定义等。

接着我在工程根目录下创建了一个目录include,将生成的头文件mvinclude目录下。


四、
创建helloworld.c并编译生成动态链接库helloworld.so

首先编写代码如下(推荐在vim或者其他可视化编辑软件中):

4.bmp

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,结果如下:

5.bmp

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

    由于我当前使用的ndk~/Project/android-ndk-r4b,并且我想让程序运行在宿主机上,于是选择第4条或者第6条,我选第6条,因此在gccflags里应该添加此路径。

    为了方便起见,我在helloworld根目录下创建一个makefile,采用递归调用Makefile,深入到各目录中进行操作,对各子目录下的Makefile统一管理:

6.bmp

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

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

7.bmp

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

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

8.bmp

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

运行结果如下:

9.bmp

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

2.
eclipse
中运行

需要为java虚拟机设置共享库路径,打开run configurations,切换到第二个选项卡arguments,在虚拟机参数输入框中输入

-Djava.library.path=/root/Project/workspace/jni/helloworld/lib/

如图所示:

10.bmp

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

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

11.bmp

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


六、 补充说明

    我的工程根目录:/root/Project/workspace/jni/helloworld/

    如果用eclipse编写代码并运行的话,需要为eclipse安装CDT插件,这样才可以支持c/c++。对于这个程序,如果不使用eclipse,可能反而更简单一些。

    另外,环境变量的设置也很重要,要根据自己系统中jdk的路径设置环境变量,设置方法可以上网搜索。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值