??????? java是属于比较上层的语言,在大多数情况下,它都可以给开发带来方便和高效率;但是在一些特定的情况下,它可能就没有低级语言那么好用了,所以就需要有能够调用其他低级语言来实现其不擅长的功能.
????? JAVA通过JNI来调用C语言的实现,其基本思想是,由java定义接口,由c实现并生成dll文件,再由java通过之前定义的接口调用具体的实现.
???? 主要步骤有:
详细解释:
?? 第一步骤不多说.
?? 第二步骤:其命令如,javah -classpath . -jni HelloWorld????? --->将当前文件夹中的HelloWorld.class编译成HelloWorld.h;
?? 第三步骤:将h文件加入到c项目中,并实现.这个也不细述.若不太明白可以参见JNI中另外的一篇文章
?? 第四步骤:就是将上一步生成的dell文件放在java项目的根路径.
现在就可以测试下了.测试类中在static块中使用System.loadLibrary("hello"); 来加载hello.dell文件.
加载成功后就可以像调用普通的java类一样调用了.
?
接下来给出一个实例:
java代码(为简单起见,不加入任何包):
?
public class HelloWorld { public native void displayHelloWorld(String msg); public native String formatInput(String input); static { System.loadLibrary("hello"); } public static void main(String[] args) { HelloWorld helloWorld = new HelloWorld(); helloWorld.displayHelloWorld("中文"); System.out.println(helloWorld.formatInput("中文您好!")); } }?生成的h文件:
?
?
/* DO NOT EDIT THIS FILE - it is machine generated */ #include "jni.h" /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: displayHelloWorld * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject, jstring); /* * Class: HelloWorld * Method: formatInput * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_HelloWorld_formatInput (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif?自动生成的可能是 #include <jni.h>,若你的jni.h文件不是在文件头的默认目录中,那么可以改成用引号的方式;
?
两者的区别就在于其查找的方式不一样,引号的方式是在当前目录下查找. 接下来是其实现:/* Replace "dll.h" with the name of your header */ #include "HelloWorld.h" #include <stdio.h> #include <string.h> #include <windows.h> #include "stdlib.h" JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *env, jclass obj, jstring jMsg ) { /* const char *str = (*env)->GetStringUTFChars(env, jMsg, 0); */ const char * str = jstringToWindows(env,jMsg); printf("hello , %s !",str); return ; } JNIEXPORT jstring JNICALL Java_HelloWorld_formatInput (JNIEnv *env, jclass obj, jstring jMsg) { /*nst char *str = (*env)->GetStringUTFChars(env, jMsg, 0);*/ const char * str = jstringToWindows( env, jMsg ); char * Buf_Return; Buf_Return = (char*)malloc(1024); sprintf(Buf_Return,"您的輸入是:%s",str); jstring recv_buf; recv_buf = WindowsTojstring(env ,Buf_Return); return recv_buf; /* char * str = "hello wang wu!"; jstring rtn; rtn = (*env)->NewStringUTF(env, str); return rtn; */ } char* jstringToWindows( JNIEnv *env, jstring jstr ) { int length = (*env)->GetStringLength(env,jstr ); const jchar* jcstr = (*env)->GetStringChars(env,jstr, 0 ); char* rtn = (char*)malloc( length*2+1 ); int size = 0; size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL ); if( size <= 0 ) { return NULL; } (*env)->ReleaseStringChars(env,jstr, jcstr ); rtn[size] = 0; return rtn; } jstring WindowsTojstring( JNIEnv* env, char* str ) { jstring rtn = 0; int slen = strlen(str); unsigned short* buffer = 0; if( slen == 0 ) rtn = (*env)->NewStringUTF(env,str ); else { int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 ); buffer = malloc( length*2 + 1 ); if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 ) rtn = (*env)->NewString( env, (jchar*)buffer, length ); } if( buffer ) free( buffer ); return rtn; }?上面这段代码中有处理过中文的参数,在windows系统下不会出现乱码问题.至于其他系统上就没测试过.