1. 程式人生 > >在C++中呼叫Jieba進行中文分詞

在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();                          
}