(一)说明
其实去年智能设计竞赛的时候就用过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);
}