java 通过JNI 调用C/C++ 程序_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > java 通过JNI 调用C/C++ 程序

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

 2013/11/13 12:45:17  sea878412  程序员俱乐部  我要评论(0)
  • 摘要:java是属于比较上层的语言,在大多数情况下,它都可以给开发带来方便和高效率;但是在一些特定的情况下,它可能就没有低级语言那么好用了,所以就需要有能够调用其他低级语言来实现其不擅长的功能.JAVA通过JNI来调用C语言的实现,其基本思想是,由java定义接口,由c实现并生成dll文件,再由java通过之前定义的接口调用具体的实现.主要步骤有:编写.java文件,其中c中的函数要用publicnativestatic修饰;编译.java文件为.class文件,使用javah生成.h文件;按照
  • 标签:程序 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代码(为简单起见,不加入任何包):

?

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系统下不会出现乱码问题.至于其他系统上就没测试过.
发表评论
用户名: 匿名