Android NDK 开发之(一) 管中窥豹

因为项目需要,最近开始用Android开发,想使用一些线程的C\C++代码,所有,了解了下 NDK的使用。虽然网上的相关教程一找一大把,学习的过程中也借鉴了不少 ,不过感觉还是自己写一边,权当作是加深印象啦。
    JNI, java nativa interface, 是通过虚拟机来实现 java 和本地代码(主要是C\C++)进行相互调用的一种技术。 鄙人对 Java 不是很熟,关于虚拟机啥的也说不上太多,就不在这里多说了。
    
    在Android里面调用C之前,先看看在本地如何用java来调用C函数罢,操作起来也就那么几步:


编写java类 HelloJNI.java

/** 
 * @brief A class test jni's usage  
 */  
class HelloJNI   
{  
    /** 
     * @brief native method to implemente with C  
     */  
    private native void sayHello();  
  
    /** 
     * load the native library 
     */  
    static {  
        System.loadLibrary("HelloJNI");  
    }  
  
    static public void main(String[] args) {  
        new HelloJNI().sayHello();  
    }  
}  

这里,定义了一个简单的测试类 HelloJNI, 里面会调用一个使用C实现的函数sayHello, 所以声明的时候前面有添加 native 关键字。此外,因为要用到 native code, 所以需要加载代码所在的动态链接库,System.loadLibrary("HelloJNI") 的作用就是加载 libHelloJNI.so 这个动态链接库(对应在windows下面应该是 HelloJNI.dll, 没有测试过)。也就是说,sayHello这个函数的实现最后就是在 libHelloJNI.so 这个动态链接库中, 接下来的工作就是构建这个动态链接库。


编译 java 代码

接下来,就可以编译这个java类了

viking@own:~/documents/project/jni$ javac HelloJNI.java   
viking@own:~/documents/project/jni$ javah HelloJNI   
第一行的作用就是编译得到 HelloJNI.class, 第二条编译命令的则是根据这个class生成对应的HelloJNI.h文件, 里面内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */  
#include <jni.h>  
/* Header for class HelloJNI */  
  
#ifndef _Included_HelloJNI  
#define _Included_HelloJNI  
#ifdef __cplusplus  
extern "C" {  
#endif  
/* 
 * Class:     HelloJNI 
 * Method:    sayHello 
 * Signature: ()V 
 */  
JNIEXPORT void JNICALL Java_HelloJNI_sayHello  
  (JNIEnv *, jobject);  
  
#ifdef __cplusplus  
}  
#endif  
#endif  
实际上就是定义了sayHello 这个函数接口在C语言中长啥样。 那么,接下来的工作想想便知,那就是用C或者C++来实现这个Java_HelloJNI_sayHello 函数,并且将之打包到libHelloJNI.so 里面去。


本地代码生成

新建一个jniHello.c, 内容如下:

#include <jni.h>  
#include <stdio.h>  
  
#include "HelloJNI.h"  
  
JNIEXPORT void JNICALL Java_HelloJNI_sayHello  
  (JNIEnv * env, jobject obj)  
{  
    printf("Hello, JNI!\n");  
}  
so easy的一个文件。 那么,接下来就把他编译成 libhelloJNI.so啦, 一下下的事情而已:
gcc -I/usr/lib/jvm/java-6-openjdk-i386/include/ -shared -o libHelloJNI.so HelloJNI.c  
至此就生成的到了libHelloJNI.so。
至于java的include路径,可以使用:

viking@own:~/documents/project/jni$ ls -l `which java`   
lrwxrwxrwx 1 root root 22 Jun 20 13:55 /usr/bin/java -> /etc/alternatives/java  
可以看到还是一个软链接,继续使用 ls,
viking@own:~/documents/project/jni$ ls -l /etc/alternatives/java  
lrwxrwxrwx 1 root root 45 Jun 20 13:55 /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk-i386/jre/bin/java  
可以知道当前系统中使用的 /usr/lib/jvm/java-6-openjdk-i386 下的java开发文件,所以jni路径就是对应的include目录了。


运行结果

最后,就可以运行测试结果啦:
viking@own:~/documents/project/jni$ java HelloJNI   
Hello, JNI!  
从上面可以看出来,使用java调用C\C++其实很简单,首先定义要用的函数,生成对应的函数接口(*.h)文件,然后,就是实现这些接口并打包到一个动态链接库中。最后,就是在java代码中加载这个动态链接库,调用相应的函数了。


下一步,就是将怎么样利用NDK来实现同样的功能了。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值