(一)說明
其實去年智能設計競賽的時候就用過JNI調用哈工大的分詞dll,這次換用系裏mandel老師的分詞器(segtag.dll)。
JAVA調用dll要通過C/C++,因此首先需要在C/C++裏先調用要調用的segtag.dll,然後再通過JNI的方法生成一個新的dll,JAVA從而調用新的dll。
(二)VC調用dll方法
segtag.dll中主要接口函數:
int init_seg(char *errmsg);
/*描述:初始化切分引擎。如果有錯,會在errmsg中返回錯誤串。請保證傳遞至少256字節的緩衝區 */
int seg_sent(wchar_t *pw, int len, char * textoutbuf, int buflen);
/*描述:進行分詞
參數:
pw 指向要切分的漢語文本。
len 指向文本的長度(以wchar爲單位)。
textoutbuf 指向存放切分結果文本的緩衝區。
buflen 指明緩衝區長度(以字節爲單位)。
返回值:
true:成功 false,失敗。可能是緩衝區太小。
*/
void set_tagmode(TTagMode mode);
/*描述:設置切分方式。影響seg_sent的返回結果
參數:
mode 切分方式:分爲切分標註(tag_normal),只切分(tag_no),命名實體識別(tag_namex)等多種。
*/
在VC中調用該dll的方法如下:
#include <windows.h>
typedef enum {tag_normal, tag_no, tag_namex, tag_neon, tag_only} TAGMODE;
int (__stdcall* init_seg)(char *errmsg); //函數指針,全局變量
int (__stdcall* seg_sent)(wchar_t *pw, int len, char * outbuf, int buflen);
void (__stdcall* set_tagmode)(TAGMODE mode);//需先定義枚舉類型
1. 加載動態鏈接庫
HMODULE h= LoadLibrary(“dll//segtag.dll”);
If(h!=NULLL){
}
2. 導出函數
init_seg = (int(__stdcall *)(char *errmsg))GetProcAddress(h, "init_seg");//函數名
3. 調用函數
init_seg(buff)
4. 釋放鏈接庫
FreeLibrary(h);
(三)備註
1.wchar_t是是一種擴展的字符存儲方式。seg_sent的第一個參數便是該類型的指針,作者在C版本的Demo中typedef爲unsigned short。以下是char*轉換爲wchar_t的代碼:
inline wchar_t* AnsiToUnicode( const char* szStr ){
//char*轉換爲wchar_t
int nLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, NULL, 0 );
if (nLen == 0)return NULL;
wchar_t* pResult = new wchar_t[nLen];
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, pResult, nLen );
return pResult;
}
2.包裝後的核心函數分詞SegSen:
string SegSen(string line){
wchar_t* wbuf=AnsiToUnicode((char*)line.c_str());
char*buf;
int iLen=line.length()+INITLEN;
bool flagEx=false;
while(iLen<MAXLEN){//可能初次分配的空間不夠
buf=new char[iLen];
if(!seg_sent(wbuf, wcslen(wbuf), buf, strlen(buf))) {//buf是指針,其內容長度需用strlen,而不是sizeof,否則就會是4
iLen+=MAGICLEN;
}
else{
flagEx=true;
break;
}
}
if(!flagEx){ //超過行的既定的最大長度
printf("分詞文本超過行的既定最大長度!\n");
return NULL;
}
return string(buf);
}