1.准备java 程序
testdll.java,内容为:
public class testdll {
static {
System.loadLibrary("goodluck"); //载入库名,库的扩展名字究竟是DLL还是SO,由系统自己判断。
}
//还需对将要调用的方法做本地声明,关键字为native。且只需要声明,而不需要具体实现
public native static int get();
public native static void set(int i);
public static void main(String[] args) {
testdll test = new testdll();
test.set(10);
System.out.println(test.get());
}
}
然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。
用javac testdll.java编译它,会生成testdll.class。
再用javah testdll,则会在当前目录下生成testdll.h文件,内容如下:
#include
#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
在具体实现的时候,我们只关心两个函数原型
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
这里JNIEXPORT和JNICALL都是JNI的关键字,函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。
下面我们用testdll.cpp文件具体实现这两个函数;
#include "testdll.h"
int i = 0;
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)
{
i = j;
}
编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件,名字为goodluck.dll。把goodluck.dll拷贝到testdll.class的目录下(或者加入环境变量中),java testdll运行它。
对于最重要得参数传递,字长不一样,因此,需要转换。比如传递字符串,java文件中参数为byte[] param,c文件中为jbyteArray,转换可以如下进行:
jsize theArrayLengthJ = (*env)->GetArrayLength(env,param); //得到本地字长
jbyte * arrayBody = (*env)->GetByteArrayElements(env,param,0);//得到本地元素
char* str=(char *)arrayBody;
main中:
byte[] temp = {0}; //字符串末尾补0
String str= "早上好";
byte[] bb= str.getBytes("gbk");
byte[] lastBB = new byte[str.length + temp.length]; //得到最终要传递得参数
就是在传递字节数组到C程序中时,最后的结尾一定要以0结束。