Java JNI 调用C++ API及中文编码问题
openkk
12年前
Java调用C++可以通过JNI声明native方法进行调用,主要步骤有:
1. 声明类及相关nativ方法,加载要调用的C++库
package bupt.cist.nlp.ner; public class ChineseNER { static{ System.loadLibrary("CIST_NER"); } public ChineseNER(){ } public native void say(String msg); public native String process(String line); }2. 到源码目录下,通过命令javah -jni bupt.cist.nlp.ner.ChineseNER编译类 ,生成.h头文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include "jni.h" /* Header for class bupt_cist_nlp_ner_ChineseNER */ #ifndef _Included_bupt_cist_nlp_ner_ChineseNER #define _Included_bupt_cist_nlp_ner_ChineseNER #ifdef __cplusplus extern "C" { #endif /* * Class: bupt_cist_nlp_ner_ChineseNER * Method: say * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_bupt_cist_nlp_ner_ChineseNER_say (JNIEnv *, jobject, jstring); /* * Class: bupt_cist_nlp_ner_ChineseNER * Method: process * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_bupt_cist_nlp_ner_ChineseNER_process (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
3. 新建CIST_NER的dll工程,加载.h头文件,编写cpp文件实现dll库
#include <iostream> #include <string> #include "bupt_cist_nlp_ner_ChineseNER.h" #include "windows.h" using namespace std; char* jstringToWindows( JNIEnv *env, jstring jstr ) { int length = env->GetStringLength(jstr); const jchar* jcstr = env->GetStringChars(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(jstr, jcstr); rtn[size] = 0; return rtn; } 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; } char* U2G(const char* utf8) { int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); wchar_t* wstr = new wchar_t[len+1]; memset(wstr, 0, len+1); MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len); len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); char* str = new char[len+1]; memset(str, 0, len+1); WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL); if(wstr) delete[] wstr; return str; } char* G2U(const char* gb2312) { int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0); wchar_t* wstr = new wchar_t[len+1]; memset(wstr, 0, len+1); MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len); len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); char* str = new char[len+1]; memset(str, 0, len+1); WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL); if(wstr) delete[] wstr; return str; } JNIEXPORT void JNICALL Java_bupt_cist_nlp_ner_ChineseNER_say(JNIEnv *env, jobject obj, jstring msg) { const char* pmsg = env->GetStringUTFChars(msg, NULL); cout << pmsg << endl; } JNIEXPORT jstring JNICAL Java_bupt_cist_nlp_ner_ChineseNER_process(JNIEnv *env, jobject obj, jstring line) { const char* pmsg = jstringToWindows(env, line); cout << pmsg << endl; // process return WindowsTojstring(env, res.c_str()); }4. 编译生成dll库,放在java工程目录下即可调用
package cpp; import bupt.cist.nlp.ner.*; public class test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ChineseNER a = new ChineseNER(); String line = "星期一中国北京"; System.out.println(line); String b = a.process(line); a.say(b); } }
参考资料:
http://hi.baidu.com/08wschen/blog/item/27a298fcc86f6c3b5c6008ca.html
http://www.vckbase.com/index.php/wv/1327
http://blog.csdn.net/qq675927952/article/details/7496035