Java JNI 调用C++ API及中文编码问题

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 
#include 
#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


你可能感兴趣的:(Java)