读书人

jni 运用 【转载】

发布时间: 2012-08-30 09:55:54 作者: rapoo

jni 使用 【转载】

? JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。  JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

?JNI在Windows上的使用运行环境


CPU : AMD Moblie Athlon 64 3200+
Mem : 1024 MB

OS : Windows xp sp2
JDK : java version "1.5.0_06"
IDE : Eclipse 3.1.2? 、? Microsoft Visual Studio 2005


编写JAVA 代码

//JNITest.java

/**
?* @author chunyv
?*
?*/
public class JNITest {

?/**
? * @param args
? */
?
?static
?{
?? try
?? {
????? System.loadLibrary("JNITest");
?? }
?? catch(Exception e)
?? {
?????? System.out.println("load library failure!");
?? }
?}
?
?public native static void version();
?
?public native static void setint(int i);
?public native static int getint();
?
?public native static void setstr(String str);
?public native static String getstr();
?
?public native static void setgbk(byte[] gbkstr);
?public native static byte[] getgbk();
?
?public static void main(String[] args) {
??// TODO Auto-generated method stub
??String test = "Hello World!";
??String test2 = "你好!\n\t\t--chunyv";
??System.out.println("Proc Start");
??byte[] end = {0};

??try
??{
???byte[] mybytedb = test2.getBytes("gbk");
???byte[] mybyte = new byte[mybytedb.length + end.length];
???System.arraycopy(mybytedb , 0 , mybyte , 0 ,mybytedb.length);
???System.arraycopy(end , 0 , mybyte , mybytedb.length , end.length);
???
???
???JNITest jnitest = new JNITest();
???
???jnitest.setint(6);
???System.out.println("setint ok");
???System.out.println("get int form library :"+jnitest.getint());
???System.out.println("getint ok");
???
???jnitest.setstr(test);???
???System.out.println("setstr ok");
???
???System.out.println(jnitest.getstr());
???System.out.println("getstr ok");
???
???jnitest.setgbk(mybyte);
???System.out.println("setgbk ok");
???
???System.out.println(jnitest.getgbk());
???System.out.println("getgbk ok");
???
???jnitest.version();
??}
??catch(Exception e)
??{
???e.printStackTrace();
??}
?}

}


生成 .h 文件


javac JNITest.java
javah JNITest


实现 JNITest.h 中的方法

/*
* author chunyv
* JNITest dll
*/

#include "JNITest.h"
#include <windows.h>


JNIEXPORT void JNICALL Java_JNITest_version
? (JNIEnv *, jclass)
{
?printf("JNI Test\n\t\t--chunyv");
}


JNIEXPORT void JNICALL Java_JNITest_setint
? (JNIEnv *, jclass, jint ii)
{
?i = ii;
}


JNIEXPORT jint JNICALL Java_JNITest_getint
? (JNIEnv *, jclass)
{
?return i;
}
?

JNIEXPORT void JNICALL Java_JNITest_setstr
? (JNIEnv * env, jclass, jstring jstr)
{?
?jboolean test = true;

?memset(str , 0 , sizeof(str));

?sprintf_s(str ,env->GetStringUTFChars(jstr,&test));

?env->ReleaseStringUTFChars(jstr , NULL);
}

JNIEXPORT jstring JNICALL Java_JNITest_getstr
? (JNIEnv * env, jclass)
{?
?return WindowsTojstring(env , str);
}

JNIEXPORT void JNICALL Java_JNITest_setgbk
? (JNIEnv * env, jclass, jbyteArray myjbyte)
{
?memset(strgbk , 0 , sizeof(strgbk));

?sprintf_s(strgbk ,(char *)env->GetByteArrayElements(myjbyte,0));
}

JNIEXPORT jstring JNICALL Java_JNITest_getgbk
? (JNIEnv * env, jclass)
{?
?return WindowsTojstring(env , strgbk);
}

jstring WindowsTojstring( JNIEnv* env, char* str_tmp )
{
??? jstring rtn = 0;
??? int slen = (int)strlen(str_tmp);
??? unsigned short * buffer = 0;
???
?if( slen == 0 )
?{
??????? rtn = env->NewStringUTF(str_tmp );
?}
??? else
??? {
??????? int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str_tmp, slen, NULL, 0 );

??????? buffer = (unsigned short *)malloc( length*2 + 1 );
???????
??if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str_tmp, slen, (LPWSTR)buffer, length ) >0 )
??{
??????????? rtn = env->NewString(? (jchar*)buffer, length );
??}
??? }

??? if( buffer )
?{
??????? free( buffer );
?}

??? return rtn;
}


将生成的JNITest.dll 放到 .class 所在的目录 测试 jni 运用 【转载】


java JNITest

Proc Start
setint ok
get int form library :6
getint ok
setstr ok
Hello World!
getstr ok
setgbk ok
你好!
??????????????? --chunyv
getgbk ok
JNI Test
??????????????? --chunyv


JNI 在 FreeBSD 上的应用?

运行环境

CPU : Intel(R) Pentium(R) 4 CPU 2.40GHz (2393.94-MHz 686-class CPU)
Mem : 512 MB

OS : FreeBSD 6.2-PRERELEASE
JDK : java version "1.5.0"
IDE : vim + gcc 3.4.4

java代码同上 生成 .h 文件同上 实现 JNITest.h 中的方法

/*
* author chunyv
* JNITest so
* add "int? FreeBSD2Jstring(char * src ,
*??char * dst,
*??int * len);" into JNITest.h
*/

#include <stdio.h>
#include <iconv.h>
#include <stdlib.h>
#include <string.h>
#include "JNITest.h"

int i = 0;
char str[1024];
char strgbk[1024];

JNIEXPORT void JNICALL Java_JNITest_version
? (JNIEnv *env, jclass jc)
{
?printf("JNI Test\n\t\t--chunyv\n");
}


JNIEXPORT void JNICALL Java_JNITest_setint
? (JNIEnv * env, jclass jc, jint ii)
{
?i = ii;
}


JNIEXPORT jint JNICALL Java_JNITest_getint
? (JNIEnv * env, jclass jc)
{
?return i;
}
?

JNIEXPORT void JNICALL Java_JNITest_setstr
? (JNIEnv * env, jclass jc, jstring jstr)
{?
?jboolean test = 1;

?memset(str , 0 , sizeof(str));

?sprintf(str ,(*env)->GetStringUTFChars(env ,jstr,&test));

?(*env)->ReleaseStringUTFChars(env ,jstr , NULL);
}

JNIEXPORT jstring JNICALL Java_JNITest_getstr
? (JNIEnv * env, jclass jc)
{?
?return (*env)->NewStringUTF(env ,str);
}

JNIEXPORT void JNICALL Java_JNITest_setgbk
? (JNIEnv * env, jclass jc, jbyteArray myjbyte)
{
?memset(strgbk , 0 , sizeof(strgbk));

?sprintf(strgbk ,(char *)(*env)->GetByteArrayElements(env ,myjbyte,0));
}

JNIEXPORT jstring JNICALL Java_JNITest_getgbk
? (JNIEnv * env, jclass jc)
{?
?char test[1024] ;
?sprintf(test ,strgbk);
?int len = (int ) strlen(strgbk);
?
?if( FreeBSD2Jstring(test , strgbk ,&len ))
?{
??printf("convert error\n");
??return NULL;
?}
?
?return (*env)->NewStringUTF(env ,strgbk);
}

int? FreeBSD2Jstring(char * src ,
??char * dst,
??int * len)
{
?size_t n_in = strlen(src);
?size_t n_out = *len+2;
?
?memset(dst , 0 , n_out);
??
?iconv_t test = iconv_open("UTF-8","GBK");
?if(test == (iconv_t)-1)
?{
??printf("iconv open error\n");
??return -1;
?}
?
?if((size_t)-1 == iconv(test ,(const char **) & src ,&n_in , & dst , &n_out))
?{
??printf("iconv convert error\n");
??return -1;
?}
?
?if(test)
?{
??iconv_close(test);
?}

?*len = n_out;

?return 0;
}


编译 .c 文件,将生成的库文件放到.class 所在目录并测试 .class

编译库文件
gcc -Wall -fPIC -shared -o libJNITest.so -I /usr/local/diablo-jdk1.5.0/include/ -I /usr/local/diablo-jdk1.5.0/include/freebsd/ -I /usr/local/include/ -liconv -L /usr/local/lib/ JNITest.c

测试 .class
java -Djava.library.path=./ JNITest

测试结果

Proc Start
setint ok
get int form library :6
getint ok
setstr ok
Hello World!
getstr ok
setgbk ok
你好!
??????????????? --chunyv
getgbk ok
JNI Test
??????????????? --chunyv

?

JNI在Linux上的使用请参阅 《JNI在FreeBSD上的使用》部分

注:实例仅供参考,转载请注明出处,欢迎交流学习,谢谢!!

读书人网 >移动开发

热点推荐