JNI学习笔记

主机环境:UBUNTU10.10

编译器:android-ndk-r8b

由于在编写android程序时需要用到C语言编写的库函数,因此涉及到了JNI知识,在此记录下一些心得,学习JNI利用NDK提供的最简单的例子来做下示范,在NDK目录下有一个samples目录,其中放有一些jni的示例,这里我们用最简单的例子hello-jni

将hello-jni目录拷贝到/key_C/android目录下,这个是我的jni程序目录,大家可以自行设置,进入该目录下的jni目录,可以看到两个文件Android.mk和hello-jni.c,其中Android.mk文件相当于linux下的Makefile文件,hello-jni.c是我们需要用到的库函数实现体,打开该文件

#include <string.h>
#include <jni.h>

/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java
 */
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}

可以看到文件很简单,因为是jni编程所以先要包含jni.h头文件,(欲哭无泪,写了好久才写好,居然保存失败,在一刷新就只剩下这么点了,又要重新写,唉~~~)

文件中也指明了java代码所在的路径,我们可以看到该函数的名字有点长,我们先分析哈,首先是返回类型jstring,涉及到jni编程

Java类型     本地类型     描述 
boolean     jboolean     C/C++8位整型 
byte     jbyte     C/C++带符号的8位整型 
char     jchar     C/C++无符号的16位整型 
short     jshort     C/C++带符号的16位整型 
int     jint     C/C++带符号的32位整型 
long     jlong     C/C++带符号的64位整型e 
float     jfloat     C/C++32位浮点型 
double     jdouble     C/C++64位浮点型 
Object     jobject     任何Java对象,或者没有对应java类型的对象 
Class     jclass     Class对象 
String     jstring     字符串对象 
Object[]     jobjectArray     任何对象的数组 
boolean[]     jbooleanArray     布尔型数组 
byte[]     jbyteArray     比特型数组 
char[]     jcharArray     字符型数组 
short[]     jshortArray     短整型数组 
int[]     jintArray     整型数组 
long[]     jlongArray     长整型数组 
float[]     jfloatArray     浮点型数组 
double[]     jdoubleArray     双浮点型数组 
上面是一些数据类型的对应表,

接着是Java,这个是固定的,后面是android工程的包名以下划线隔开而不是以点分割,接着是类名,指明该函数是由那个类来调用,最后是函数名stringFromJNI以及参数JNIEnv* env,jobject thiz,前者是一个指向函数列表的指针,后面相当于this指针,这两个参数是固定的,如果读者有自己想要传递的参数加在后面即可。

函数实现体中只有一句代码将“hello from JNI!”通过env传递给主调函数。

下面说下Android.mk文件

Android.mk文件相当于linux下的Makefile文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

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

include $(BUILD_SHARED_LIBRARY)

这个格式是一个固定的mk文件编写格式,第一句话是指明当前目录即mk所在目录;第二句话是清除LOCAL_XXX变量,不然会对我们编译产生影响;第三句话是指明所要生成的库的名字;第四句话是指明需要的C文件,最后一句话是指明生成共享库,在该目录下执行¥NDK/ndk-build,会在libs目录下生成所需要的libhello-jni.so库文件

打开java文件

package com.example.hellojni;

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;


public class HelloJni extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        /* Create a TextView and set its content.
         * the text is retrieved by calling a native
         * function.
         */
        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );	//调用函数
        setContentView(tv);
    }

    /* A native method that is implemented by the
     * 'hello-jni' native library, which is packaged
     * with this application.
     */
    public native String  stringFromJNI();	//声明函数

    /* This is another native method declaration that is *not*
     * implemented by 'hello-jni'. This is simply to show that
     * you can declare as many native methods in your Java code
     * as you want, their implementation is searched in the
     * currently loaded native libraries only the first time
     * you call them.
     *
     * Trying to call this function will result in a
     * java.lang.UnsatisfiedLinkError exception !
     */
    public native String  unimplementedStringFromJNI();	//声明函数

    /* this is used to load the 'hello-jni' library on application
     * startup. The library has already been unpacked into
     * /data/data/com.example.hellojni/lib/libhello-jni.so at
     * installation time by the package manager.
     */
    static {
        System.loadLibrary("hello-jni");	//加载库文件
    }
}
在java文件中调用C语言函数,首先需要加载库文件,然后用native关键字声明该函数,只需写函数名字即可,env和thiz参数省略,只需写自己所需要的参数即可,这里为空。之后就可以在程序中调用该函数了,这里是用TextView控件显示被调函数返回的字符串内容,效果如下:

JNI学习笔记_第1张图片

小弟才疏学浅,如果错误请大家指正,以便小弟得到提升。写这个文章失败了两次,所以以后大家写文章千万记得随时保存,小蝶就是血淋淋的教训那!!!

你可能感兴趣的:(java,exception,String,jni,library,makefile)