`

java 通过JNI 调用C/C++ 程序

    博客分类:
  • Java
 
阅读更多

       java是属于比较上层的语言,在大多数情况下,它都可以给开发带来方便和高效率;但是在一些特定的情况下,它可能就没有低级语言那么好用了,所以就需要有能够调用其他低级语言来实现其不擅长的功能.

      JAVA通过JNI来调用C语言的实现,其基本思想是,由java定义接口,由c实现并生成dll文件,再由java通过之前定义的接口调用具体的实现.

     主要步骤有:

  1. 编写.java文件,其中c中的函数要用public native static修饰;
  2. 编译.java文件为.class文件,使用javah生成.h文件;
  3. 按照.h文件中的函数形式在c中实现函数;
  4. 生成.dll文件,拷贝到java工程中.

详细解释:

   第一步骤不多说.

   第二步骤:其命令如,javah -classpath . -jni HelloWorld      --->将当前文件夹中的HelloWorld.class编译成HelloWorld.h;

   第三步骤:将h文件加入到c项目中,并实现.这个也不细述.若不太明白可以参见JNI中另外的一篇文章

   第四步骤:就是将上一步生成的dell文件放在java项目的根路径.

现在就可以测试下了.测试类中在static块中使用System.loadLibrary("hello"); 来加载hello.dell文件.

加载成功后就可以像调用普通的java类一样调用了.

 

接下来给出一个实例:

java代码(为简单起见,不加入任何包):

 

Java代码  收藏代码
  1. public class HelloWorld {  
  2.     public native void displayHelloWorld(String msg);  
  3.       
  4.     public native String formatInput(String input);  
  5.       
  6.     static {  
  7.         System.loadLibrary("hello");   
  8.     }  
  9.    
  10.     public static void main(String[] args) {  
  11.         HelloWorld helloWorld = new HelloWorld();  
  12.         helloWorld.displayHelloWorld("中文");  
  13.         System.out.println(helloWorld.formatInput("中文您好!"));  
  14.     }  
  15. }  
 生成的h文件:

 

 

C代码  收藏代码
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include "jni.h"  
  3. /* Header for class HelloWorld */  
  4.   
  5. #ifndef _Included_HelloWorld  
  6. #define _Included_HelloWorld  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /* 
  11.  * Class:     HelloWorld 
  12.  * Method:    displayHelloWorld 
  13.  * Signature: (Ljava/lang/String;)V 
  14.  */  
  15. JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld  
  16.   (JNIEnv *, jobject, jstring);  
  17.   
  18. /* 
  19.  * Class:     HelloWorld 
  20.  * Method:    formatInput 
  21.  * Signature: (Ljava/lang/String;)Ljava/lang/String; 
  22.  */  
  23. JNIEXPORT jstring JNICALL Java_HelloWorld_formatInput  
  24.   (JNIEnv *, jobject, jstring);  
  25.   
  26. #ifdef __cplusplus  
  27. }  
  28. #endif  
  29. #endif  
 自动生成的可能是 #include <jni.h>,若你的jni.h文件不是在文件头的默认目录中,那么可以改成用引号的方式;

 

两者的区别就在于其查找的方式不一样,引号的方式是在当前目录下查找.
接下来是其实现:
C代码  收藏代码
  1. /* Replace "dll.h" with the name of your header */  
  2. #include "HelloWorld.h"  
  3. #include <stdio.h>  
  4. #include <string.h>   
  5. #include <windows.h>   
  6. #include "stdlib.h"  
  7.   
  8. JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld  
  9.   (JNIEnv *env, jclass  obj, jstring jMsg )  
  10. {  
  11.     /* 
  12.     const char *str = (*env)->GetStringUTFChars(env, jMsg, 0); 
  13.     */  
  14. const char * str = jstringToWindows(env,jMsg);  
  15. printf("hello , %s !",str);  
  16. return ;  
  17. }  
  18.   
  19. JNIEXPORT jstring JNICALL Java_HelloWorld_formatInput  
  20.   (JNIEnv *env, jclass  obj, jstring jMsg)  
  21. {  
  22.     /*nst char *str = (*env)->GetStringUTFChars(env, jMsg, 0);*/  
  23. const char * str = jstringToWindows( env, jMsg );  
  24.   
  25. char * Buf_Return;  
  26. Buf_Return = (char*)malloc(1024);  
  27. sprintf(Buf_Return,"您的輸入是:%s",str);  
  28. jstring recv_buf;  
  29. recv_buf = WindowsTojstring(env ,Buf_Return);  
  30. return recv_buf;  
  31. /* 
  32. char * str = "hello wang wu!";   
  33. jstring rtn;   
  34. rtn = (*env)->NewStringUTF(env, str);   
  35. return rtn;  
  36. */  
  37. }  
  38.   
  39. char* jstringToWindows( JNIEnv *env, jstring jstr )  
  40. {  
  41. int length = (*env)->GetStringLength(env,jstr );  
  42. const jchar* jcstr = (*env)->GetStringChars(env,jstr, 0 );  
  43. char* rtn = (char*)malloc( length*2+1 );  
  44. int size = 0;  
  45. size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );  
  46. if( size <= 0 )  
  47.     {  
  48. return NULL;  
  49.     }  
  50. (*env)->ReleaseStringChars(env,jstr, jcstr );  
  51. rtn[size] = 0;  
  52. return rtn;  
  53. }  
  54.   
  55.   
  56. jstring WindowsTojstring( JNIEnv* env, char* str )  
  57. {  
  58. jstring rtn = 0;  
  59. int slen = strlen(str);  
  60. unsigned short* buffer = 0;  
  61. if( slen == 0 )  
  62. rtn = (*env)->NewStringUTF(env,str );  
  63. else  
  64. {  
  65. int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );  
  66. buffer = malloc( length*2 + 1 );  
  67. if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )  
  68. rtn = (*env)->NewString( env, (jchar*)buffer, length );  
  69. }  
  70. if( buffer )  
  71. free( buffer );  
  72. return rtn;  
  73. }   
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics