java是属于比较上层的语言,在大多数情况下,它都可以给开发带来方便和高效率;但是在一些特定的情况下,它可能就没有低级语言那么好用了,所以就需要有能够调用其他低级语言来实现其不擅长的功能.
JAVA通过JNI来调用C语言的实现,其基本思想是,由java定义接口,由c实现并生成dll文件,再由java通过之前定义的接口调用具体的实现.
主要步骤有:
- 编写.java文件,其中c中的函数要用public native static修饰;
- 编译.java文件为.class文件,使用javah生成.h文件;
- 按照.h文件中的函数形式在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("中文您好!"));
- }
- }
- /* 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
两者的区别就在于其查找的方式不一样,引号的方式是在当前目录下查找.
接下来是其实现:
- /* 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;
- }