JNI即java native interface 的简称,由于java可移植性强的特点使得java很受欢迎。但正是这个特点使得java与本地机器内部的交互变得不是很方便,约束了它的功能。解决这个问题的办法是JNI编程!
java通过JNI调用本地方法,本地方法以库文件的形式存在,windows系统为.dll文件,linux/unix系统为.so文件,当然还有一种静态链接库文件。下面介绍JNI的编写步骤:
一·要在java中调用JNI,首先创建在工程中创建.java文件,如下所示;
运行javac ps2_driver.java,生成.class文件
然后用javah编译生成c/c++的.h文件:javah -jni ps2_driver,生成如下所示文件
这个文件是不让修改的 ,可以看到,其中包含生成的方法:
JNIEXPORT void JNICALL Java_ps2_1driver_send_1message
(JNIEnv *, jobject, jintArray);
这里 JNIEXPORT 和 JNICALL 都是 JNI 的关键字,表示此函数是要被 JNI 调用的。而 jint Arrar是以 JNI 为中介使 JAVA 的 int 类型数组与本地的 int数组 沟通的一种类型 。
二· 第二步,就是具体实现上面的方法,编写c/c++文件实现(相同目录下):
编译的时候需要用到jni.h和jni_md.h,用locate jni.h,locate jni_md.h查看他们所在的位置,我的如下:
/usr/lib/jvm/java-1.6.0/include/linux/jni_md.h
/usr/lib/jvm/java-1.6.0/include/jni.h
用cc编译如下:
cc -I /usr/lib/jvm/java-1.6.0/include/linux/ -I /usr/lib/jvm/java-1.6.0/include/ -I /root/workspace/ps2_driver -fPIC -shared -o libps2_driver.so ps2_driver.c
注意一定要在生成的so前面加lib,不然系统无法识别
将生成的so加到系统路径:
export LD_LIBRARY_PATH="/root/workspace/ps2_driver":$LD_LIBRARY_PATH
或者直接老被到/usr/lib目录下,就可以使用该so库了。
下面写个java测试程序测试一下:
更高级的应用以后再研究了!
java通过JNI调用本地方法,本地方法以库文件的形式存在,windows系统为.dll文件,linux/unix系统为.so文件,当然还有一种静态链接库文件。下面介绍JNI的编写步骤:
一·要在java中调用JNI,首先创建在工程中创建.java文件,如下所示;
import java.util.*;
import java.io.*;
public class ps2_driver{
//本地函数声明
public native void send(int[] bytes); //给本地函数传递int型数组参数
//加载本地共享链接库
static
{
System.loadLibrary("ps2_driver");
}
}
运行javac ps2_driver.java,生成.class文件
然后用javah编译生成c/c++的.h文件:javah -jni ps2_driver,生成如下所示文件
#include <jni.h>
#ifndef _Included_ps2_driver
#define _Included_ps2_driver
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_ps2_1driver_send
(JNIEnv *, jobject, jintArray);
#ifdef __cplusplus
}
#endif
#endif
这个文件是不让修改的 ,可以看到,其中包含生成的方法:
JNIEXPORT void JNICALL Java_ps2_1driver_send_1message
(JNIEnv *, jobject, jintArray);
这里 JNIEXPORT 和 JNICALL 都是 JNI 的关键字,表示此函数是要被 JNI 调用的。而 jint Arrar是以 JNI 为中介使 JAVA 的 int 类型数组与本地的 int数组 沟通的一种类型 。
二· 第二步,就是具体实现上面的方法,编写c/c++文件实现(相同目录下):
#include"ps2_driver.h"
#include<stdio.h>
jint *array;
JNIEXPORT void JNICALL Java_ps2_1driver_send
(JNIEnv *env, jobject obj, jintArray bytes)
{
jsize len = (*env)->GetArrayLength(env,bytes); //数组元素个数
array = (*env)->GetIntArrayElements(env,bytes,0);
int i,sum = 0 ;
printf("接收到的数据为:\n");
for(i=0;i<len;i++)
{
printf("%d",array[i]);
sum += array[i];
}
printf("\n总和为:%d\n",sum);
(*env)->ReleaseIntArrayElements(env,bytes,array,0);
return ;
}
编译的时候需要用到jni.h和jni_md.h,用locate jni.h,locate jni_md.h查看他们所在的位置,我的如下:
/usr/lib/jvm/java-1.6.0/include/linux/jni_md.h
/usr/lib/jvm/java-1.6.0/include/jni.h
用cc编译如下:
cc -I /usr/lib/jvm/java-1.6.0/include/linux/ -I /usr/lib/jvm/java-1.6.0/include/ -I /root/workspace/ps2_driver -fPIC -shared -o libps2_driver.so ps2_driver.c
注意一定要在生成的so前面加lib,不然系统无法识别
将生成的so加到系统路径:
export LD_LIBRARY_PATH="/root/workspace/ps2_driver":$LD_LIBRARY_PATH
或者直接老被到/usr/lib目录下,就可以使用该so库了。
下面写个java测试程序测试一下:
import java.io.*;
import java.util.*;
public class ps2_driver_test
{
public static void main(String args[])
{
new ps2_driver().send(new int[]{1,1,1,1,1,1,1,1,1,1,1});
}
}
显示结果如下:
更高级的应用以后再研究了!
以上这些文件都是放在同一个目录里面的!
相同原文地址:我的新浪微博