在C++中调用Jieba进行中文分词

背景

之前有个小项目用到了中文分词,但当时使用的ICTCLAS需要每个月下载证书,很不方便。后来在网上找到了一个开源的python实现的中文分词器Jieba,可以使用pip直接安装本地。但之前的项目是c++实现的,所以需要考虑跨语言的调用问题。
Python.h中提供了PyRun_SimpleString()方法,可以执行简单的python语句,但无法获取输出的数据。另外也提供了PyObject_CallObject(),可以将python命令的执行结果作为PyObject对象指针返回。

代码实现:类定义

class PyTextCut{                                 

    private:                                     
        PyObject *pName,*pModule,*pDict,*pFunc;  

    public:                                      
        PyTextCut();                             
        string cut(string input); //Jieba分词的调用入口
        ~PyTextCut();                            

    private:                                     
        int init();                              
};                                               

代码实现:初始化

PyTextCut::PyTextCut(){   
    init();               
}                         

string PyTextCut::init()
{
    Py_Initialize();                                   

    // 检查初始化是否成功 
    if ( !Py_IsInitialized() ) {                                 
        return -1;                                       
    }                                                      
    // 添加当前路径                                              
    PyRun_SimpleString("import sys");                      
    PyRun_SimpleString("reload(sys)");                     
    PyRun_SimpleString("sys.setdefaultencoding('utf8')");  

    // 载入jieba                                             
    pName = PyString_FromString("jieba");                  
    pModule = PyImport_Import(pName);                      
    if ( !pModule ) {                                      
        printf("can't find jieba");                        
        return -1;                                         
    }                                                      
    pDict = PyModule_GetDict(pModule);                     
    if ( !pDict ) {                                        
        return -1;                                         
    }                                                   
    //查找函数cut                                              
    pFunc = PyDict_GetItemString(pDict, "cut");            
    if ( !pFunc || !PyCallable_Check(pFunc) ) {            
        printf("can't find function [cut]");               
        return -1;                                         
    }   
}                                                   

代码实现:调用分词方法

string PyTextCut::cut(string input){                              
    string output = "";                                           
    PyObject *pArgs = PyTuple_New(1);                             
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("s",input.c_str()));  

    // 执行cut
    PyObject *pRet = PyObject_CallObject(pFunc, pArgs);           
    //因为返回的是生成器类型的对象,所以必须用迭代器来访问
    PyObject *iter = PyObject_GetIter(pRet);                      
    if( !iter ){                                                  
        printf("can't find iter");                                
        return input;                                             
    }                                                             
    PyObject *next = NULL;                                        
    while(true){                                                  
        next = PyIter_Next(iter);                                 
        if( !next ){                                              
            break;                                                
        }                                                         
        string str = PyString_AsString(next);                     
        output += str + " ";//将分词结果用空格隔开
    }                                                             
    Py_DECREF(pArgs);
    Py_DECREF(pRet);                                              
    Py_DECREF(iter);                                              
    return output;                                                
}                                                                 

代码实现:减少引用计数,释放资源

PyTextCut::~PyTextCut(){                      
    if(pFunc != NULL) Py_DECREF(pFunc);       
    if(pDict != NULL) Py_DECREF(pDict);       
    if(pModule != NULL) Py_DECREF(pModule);   
    if(pName != NULL) Py_DECREF(pName);       

    // 释放          
    Py_Finalize();                          
}                                              

你可能感兴趣的:(C/C++编程)