【毕设记录】JAVA下调用第三方DLL

来源:互联网 发布:win32编程 视频 编辑:程序博客网 时间:2024/04/28 12:20

(一)简述

JNI(Java Native Interface),中文为JAVA本地调用。允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

Java下要调用第三方dll,需要对该dll进行再次包装成dll,从而借助JNI对该dll进行调用。


(二)过程

1.借助之前VC下调用dll所设计的函数,首先要在Eclipse下新建类SegTag,包括:

public class SegTag {static{System.loadLibrary("lib/Tag");}public static native boolean Init(String path);public static native void SetMode(int mode);public static native void Destory();public static native String SegSen(String line);public static native void SetInfo(boolean flag);}

需注意的是必须要以public static修饰函数。此处共5个函数,以下将以核心分词函数SegSen说明。

2. 利用命令行编译,生成.class文件

Javac SegTag.java

3. 生成SegTag.h头文件

Javah SegTag

若该类在某包下,生成.h方法如下:

javah -classpath . -jni 类路径.SegTag

4.VC下新建工程,选择新建DLL工程,可选择空白DLL

5.将SegTag.h拷到工程目录下,在左边栏选择【FileView】模式,导入如图文件。

其中,jni.h和jni_md.h可从JAVA安装路径下得到(为简便起见烤到工程目录下,但随之include的方式也要有所改变,include”jni.h”)

6.以分词函数为例,从SegTag.h中将以下函数复制到SegTag.cpp中进行实现,

/* * Class:     SegTag * Method:    SegSen * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_SegTag_SegSen  (JNIEnv *, jclass, jstring);

可以看到第一个参数是调用JNI 方法时使用的 JNIEnvironment 指针。第二个参数是指向在此Java 代码中实例化的 Java 对象 SegTag 的一个句柄。其他参数是方法本身的参数。

7.实现函数

   7.1类型转换

   JNI里最复杂的就是各种数据类型的转换。而普通类型比如布尔型、整型等,比较简单;但是string、数组等较为繁琐。java内部是使用16bit的unicode编码(UTF-16)来表示字符串的,无论中文英文都是2字节; jni内部是使用UTF-8编码来表示字符串的,UTF-8是变长编码的unicode,一般ascii字符是1字节,中文是3字节; c/c++使用的是原始数据,ascii就是一个字节了,中文一般是GB2312编码,用两个字节来表示一个汉字

   Env下有2个函数可进行jstring 到char*的转换,一个是GetStringUTFChars,这个函数将得到一个UTF-8编码的字符串;另一个是 GetStringChars这个将得到UTF-16编码的字符串(即wchar_t)。无论那个函数,得到的字符串如果含有中文,都需要进一步转化成GB2312的编码,否则会产生乱码。

   由于可以直接通过GetStringChars获得wchar_t*,因此分词函数的重点便是将分词结果(char*)转换为jstring返回。

jstring WindowsTojstring( JNIEnv *env, const char* str )   {     jstring rtn = 0;     int slen = strlen(str);     unsigned short* buffer = 0;     if( slen == 0 )       rtn = env->NewStringUTF(str);      else     {       int length = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)str, slen, NULL, 0);       buffer = (unsigned short*)malloc(length*2 + 1);       if( MultiByteToWideChar(CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length) >0)         rtn = env->NewString((jchar*)buffer, length);     }     if(buffer)     free(buffer);     return rtn;   }
   7.2 其它实现

       其它实现类似于VC下调用dll。

8.编译、连接后在DEBUG文件夹下生成dll。将该文件复制到eclipse工程下,进行测试。


(三)其它

1.对于该分词系统,VC下调用dll默认的字典路径是exe下。但是JNI里默认的路径是jre/bin里。可通过打印init_seg的返回参数字符串可知错误信息。另,该函数成功调用时返回值应该是1。

调试时未考虑搜素引擎为初始化成功的情况,转而考虑过多编码问题,浪费时间。

2.JNI传参更详细,参考:

http://blog.csdn.net/rohsuton/article/details/3522214






原创粉丝点击