这里在window XP环境下用一个helloWorld,示例该如何使用jni。 一些细节请参考《android框架揭秘》这本书,写的非常详细。
一些术语:
本地代码:指用c/c++编写的原生代码。
本地方法:指用java编写的类的方法。
本地函数:区分于本地方法,指用c/c++编写函数。
1.在java类中声明本地方法
文件HelloJNI.java中的内容:
class HelloJNI { native void printHello(); // 本地方法 native void printString(String str); // 本地方法 static { System.loadLibrary("hellojni"); } // java中的静态块用于加载c/c++编写的动态库 (window下是hellojni.dll,linux下是hellojni.so) public static void main(String args[]) { HelloJNI myJNI = new HelloJNI(); // 调用本地方法(实际调用了c语言编写的本地函数) myJNI.printHello(); // 调用本地方法,对应的框架层会通过jni调用c/c++编写的对应接口 myJNI.printString("hello, this is a jni call!"); } }
2.使用javah命令生成包含JNI本地函数原型的头文件.
命令:
javac HelloJNI.java javah HelloJNI
生成 HelloJNI.h头文件,包含了c/c++本地代码的原型函数说明。
/* 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: printHello * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloJNI_printHello (JNIEnv *, jobject); /* * Class: HelloJNI * Method: printString * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_HelloJNI_printString (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
说明:
函数名称由这几部分构成:类名_本地方法名_返回值类型(共同参数)。
1.其中JNIEnv是jni接口的指针,jni本身提供许多函数用于创建java对象或调用对应方法。
2.jobject是java本地数据类型,java提供的一套与java数据类型相对应的本地类型,是的本地语言可以使用java的数据类型。不必担心不同平台(win、linux)的类型与对应的字节数不一样。因此从java中接收数据,使用java本地数据类型即可.
java类型 | java本地类型 | 占用内存大小 |
byte |
jbyte | 1 |
short | jshort | 2 |
int | jint | 4 |
long | jlong | 8 |
float
|
jfloat
|
4
|
double
|
jdouble
|
8
|
char
|
jchar
|
2
|
boolean
|
jboolean
|
1
|
类 | Jclass | |
对象 | Jobject | |
String | Jstring |
最下面三种是引用类型,还有其他几种,可参考http://java.sun.com/docs/books/jni
3.实现JNI本地函数
HelloJNI.c文件内容,编写这个代码时,首先把上面生成的.h文件里的函数原型拷贝过来,然后再修改,可以减少错误。
HelloJNI.c文件内容,编写这个代码时,首先把上面生成的.h文件里的函数原型拷贝过来,然后再修改,可以减少错误。
#include "HelloJNI.h" #include <stdio.h> /* * Class: HelloJNI * Method: printHello * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloJNI_printHello (JNIEnv *env, jobject obj) { printf("hello, world!\n"); return; } /* * Class: HelloJNI * Method: printString * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_HelloJNI_printString (JNIEnv *env, jobject obj, jstring string) { const char *str = (*env)->GetStringUTFChars(env, string, 0); printf("%s!\n", str); return; }
4.生成c共享库
cl -I"C:\Program Files\Java\jdk1.7.0\include" -I"C:\Program Files\Java\jdk1.7.0\include\win32" -LD hellojni.c -Fehellojni.dll
注意:需要安装VC++2008 Express Editions或者VS2008,在自带的Visual studio 2008 Command Prompt中输入。
上述的jdk目录(C:\Program Files\Java\jdk1.7.0)根据自己的位置修改。