PY++ 自動將你的C++程式介面封裝供python調用

來源:互聯網
上載者:User
written by pku_goldenlock at qq.com引言:

我喜歡C++的速度,我喜歡python的簡潔,我相信只用C++,python就可以解決99.99%的問題,那麼如何讓它們互動呢,這裡僅說明如何將C++的代碼介面封裝使得python可以調用c++。一個簡單的應用我寫了一個分詞器,我希望能通過網頁形式展示給別人,我覺得用django做這這件事情比用C++些XML更靈活方便。那麼如何讓python代碼能夠調用我的分詞器呢?我在前面的文章介紹過boost.python使得C++中方便調用python,boost.python入門教程 ----python 嵌入c++

python嵌入C++------ boost.python如何在C++中調用含有不定長參數tuple變數和關鍵字參數dict變數的函數, 這是所謂的python嵌入C++,

其實boost.pthon也可以用於封裝C++,使得python方便的調用C++代碼。我也寫過用swig實現C++封裝二叉樹顯示(圖形介面,控制台字元),簡單運算式求值,pyqt,swig初試....。

簡單對比boost.python和swig:

我推薦使用boost.python。boost.python對於python的擴充和嵌入即雙向都支援,對於python調用C++的需求,兩者都需要手工鞋代碼封裝需要的C++介面,但是boost.python更強大靈活更方便些。

為什麼用py++:

我很懶,我不喜歡手工去封裝,那是很機械的事情,作為一個很弱的演算法工程師我也不希望花時間去寫這些機械代碼。。。如果項目很大怎麼辦,很多介面,都要手工去寫。。。my god,我乾脆不想用python調它了。。。

例如

class_<AdRanker > ("AdRanker")
        .def("load", &AdRanker::load)
        .def("getAds", &AdRanker::getAds)
        .def("loadFile", &AdRanker::loadFile)
        .def("getAdRankInfoVec", &AdRanker::getAdRankInfoVec, return_internal_reference<>())
        .def("getAdRankInfo", &AdRanker::getAdRankInfo, return_internal_reference<>())
        .def("getSegString", &AdRanker::getSegString)
        .def("getSegStringVec", &AdRanker::getSegStringVec)
        .def("getPhraseOrgExtend", &AdRanker::getPhraseOrgExtend)
        .def("getPhraseFinalExtend", &AdRanker::getPhraseFinalExtend)
        .def("getPhraseExtendCat", &AdRanker::getPhraseExtendCat)
        ;

我希望這一切可以自動化!而PY++可以省去你手工封裝的過程協助你產生類似上面的代碼!即py++可以幫你自動產生使用boost.python手工寫的封裝代碼。

以下都是講linux環境下的安裝和使用。

PY++的安裝:
  • 安裝gccxml

py++首先依賴gccxml的分析功能解析C++代碼結構,這個很強大。。。,安裝如下

wget http://www.gccxml.org/files/v0.6/gccxml-0.6.0.tar.gz

$ mkdir gccxml-build

$ cd gccxml-build

$ cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/installation/path

$ make

$ make install

如果這個個編譯不行  ,用CVS最新的版本

cvs -d :pserver:anoncvs@www.gccxml.org:/cvsroot/GCC_XML co gccxml

  • 安裝pygccxml

svn co https://pygccxml.svn.sourceforge.net/svnroot/pygccxml pygccxml

然後進入各個子目錄發現有setup.py 的

執行python setup.py install

PY++使用樣本:

好了我們用一個最簡單的代碼進行樣本,更細節的功能有待進一步學習:

假設我們有chg.h chg.cc兩個檔案,我們要將其介面封裝為python可調用的介面。

chg.h

#ifndef chg_#define chg_#include <iostream>#include <vector>#include <string>using namespace std;class Chg{  public:    Chg():      m_age(28){ m_friend.push_back("mm");}    int getAge()    {      return m_age;    }    int friendSize()    {      return m_friend.size();    }    int m_age;    vector<string> m_friend;};void haha();#endif
chg.cc
#include "chg.h"void haha(){  cout << "hahaha" << endl;}

我們需要寫一個python指令碼協助自動完成封裝,如果你不想做進一步的細緻設定比如哪些介面被封裝,哪些不被封裝,你可以像下面這麼寫,甚至寫個指令碼協助自動產生下面的代碼。當然你要細緻設定可以去參考下py++的入門教程也很簡單。http://www.language-binding.net/pyplusplus/pyplusplus.html#

import osimport sysfrom pyplusplus import module_buildermb = module_builder.module_builder_t(         files=['chg.h'] #要需要封裝的標頭檔        ,gccxml_path='/usr/local/bin/gccxml')mb.build_code_creator( module_name='libchg_py' ) #要產生的python模組的名稱mb.code_creator.user_defined_directories.append( os.path.abspath('.') )mb.write_module( os.path.join( os.path.abspath('.'), 'chg_py.cc' ) ) #要產生的boost.python封裝好的代碼檔案的名稱
 
好了執行上面的檔案我們就可以看到chg_py.cc被產生了出來,它的樣子如下
// This file has been generated by Py++.#include "boost/python.hpp"#include "boost/python/suite/indexing/vector_indexing_suite.hpp"#include "chg.h"namespace bp = boost::python;BOOST_PYTHON_MODULE(libchg_py){    { //::std::vector< std::string >        typedef bp::class_< std::vector< std::string > > vector_less__std_scope_string__greater__exposer_t;        vector_less__std_scope_string__greater__exposer_t vector_less__std_scope_string__greater__exposer = vector_less__std_scope_string__greater__exposer_t( "vector_less__std_scope_string__greater_" );        bp::scope vector_less__std_scope_string__greater__scope( vector_less__std_scope_string__greater__exposer );        vector_less__std_scope_string__greater__exposer.def( bp::vector_indexing_suite< ::std::vector< std::string >, true >() );    }    bp::class_< Chg >( "Chg", bp::init< >() )            .def(             "friendSize"            , (int ( ::Chg::* )(  ) )( &::Chg::friendSize ) )            .def(             "getAge"            , (int ( ::Chg::* )(  ) )( &::Chg::getAge ) )            .def_readwrite( "m_age", &Chg::m_age )            .def_readwrite( "m_friend", &Chg::m_friend );    { //::haha            typedef void ( *haha_function_type )(  );                bp::def(             "haha"            , haha_function_type( &::haha ) );        }}

是的如你所見py++的功能就是自動產生boost.python代碼。。。而沒有py++你需要手工完成這些事情,py++真的很life saving。

 

好了 通過編譯chg.cc chg_py.cc 注意你要連結boost.python和python動態連結程式庫。我的CmakeList裡面是這麼寫的

add_library(chg_py SHARED chg_py.cc chg.cc)
target_link_libraries(chg_py libboost_python.so libpython2.6.so)

 

看下效果吧(注意我用的cmake會自動產生libchg_py.so):

In [1]: from libchg_py import *

In [2]: chg = Chg()

In [3]: chg.getAge()
Out[3]: 28

In [4]: print len(chg.m_friend)
1

In [5]: chg.m_friend[0]
Out[5]: 'mm'

In [6]: haha()
hahaha

 

C++有很多龐大的庫比如計算幾何相關的CGAL庫,它們大都有python介面,是不是都是這麼搞出來的呢,我估計是。。。 呵呵

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.