好久沒有寫文章了,今天整理了一些東西,在這裏分享一下。python
最近一直在想用C++封裝一些在工做中經常使用的Python擴展模塊,由於以前沒有用C++寫過相似的東西,所以一直在網上找一些文章,可是我發現好多文章都描述的不是很清晰,對於老鳥來講應該會很容易,可是像我這種初學者,確定會形成很大的困擾,由於老是出現不少的報錯,搞的頭很大,所以我將成功的案例分享一下,而且詳細的解釋下讓我產生疑惑的地方。ios
簡單描述python2.7
C++寫python擴展模塊有不少種方式,我選擇的是boost.python來編寫的,感受這個要比其餘的方式要簡單不少,寫不多的boost.python代碼就能夠,這樣就能夠更專一的去寫C++的程序。ide
boost.python的科普就沒必要多說了,能夠自行google,我也是本身google的。函數
安裝測試
這裏僅介紹Ubuntu的安裝方式:google
sudo apt-get install libboost-all-dev
或者spa
sudo apt-get install libboost-python-dev # 這種方式我沒有嘗試,大家能夠本身試試
源碼安裝也是能夠的,可是須要配置好環境變量,不然編譯的時候老是編譯不過去,當前直接在編譯的時候指定須要的路徑也是能夠的。code
C++ 代碼get
下面的例子將一些模糊的點,作了一下描述。
#include <iostream> #include <string> #include <boost/python.hpp> // 必須引入這個頭文件 using namespace boost::python; class HelloWorld{ public: HelloWorld(const std::string& name, int age); void printInfo(); private: std::string m_name; int m_age; }; HelloWorld::HelloWorld(const std::string& name, int age):m_name(name), m_age(age){ } void HelloWorld::printInfo(){ std::cout << "我叫" << m_name << ", " << m_age << "歲了" << std::endl; } void ceshi(){ std::cout << "ceshi" << std::endl; } BOOST_PYTHON_MODULE(helloworld){ // 類導出成Python可調用的動態連接庫文件的方式 class_<HelloWorld/* 類名 */, boost::noncopyable /* 單例模式,無關緊要 */ > ("helloworld", init<const std::string&, int/* init裏面就是放構造函數的參數,不須要實參 */>())//導出類中的方法 .def("printinfo", &HelloWorld::printInfo); // 普通函數導出成Python可調用的動態連接庫文件的方式 def("ceshi",&ceshi); }
編譯的命令
下面的命令是我在編譯動態連接庫文件的命令,根據本身的實際狀況修改。
# python3 g++ -shared -o helloworld.so -fPIC -I/usr/include/python3.6m/ helloworld.cpp -lpython3.6m -lboost_python3 # python2 g++ -shared -o helloworld.so -fPIC -I/usr/include/python2.7/ helloworld.cpp -lpython -lboost_python 簡單介紹下參數 -shared // 指定生成動態連接庫 -o // 生成的動態連接庫的名稱 -fPIC // 表示使用地址無關代碼 -I(大寫的i) // 表示將/usr/include/python2.7/目錄做爲第一個尋找頭文件的目錄、 -l // 指定需鏈接的庫名
沒有報錯的話會在當前目錄下生成一個名叫helloworld.so
的動態連接庫文件,直接在當前目錄進入Python Shell就能夠測試,固然你直接放入到Python的site-packages目錄中也是能夠直接在Python Shell環境中引入的。
驗證結果
>>> import helloworld >>> hw = helloworld.helloworld("lanyulei", 18) >>> hw.printinfo() 我叫lanyulei, 18歲了