使用boost.python进行混合开发
使用boost.python進行混合開發
原文請參照官網和各方參考,本文有改動!
參考鏈接:http://blog.csdn.net/lanbing510/article/details/12197901
引言:
1??簡介:
Boost.Python 是?Boost的一個組件。而?Boost是目前很紅火的準?C++標準庫,它提供了很多組件使得人們可以用?C++語言更方便地實現更多的功能。 Boost.Python就是?Boost眾多組件中的一個。但它是個特例,它的目的不是單純地增強?C++語言的功能,而是希望利用?C++語言來增強?Python語言的能力。使用?Boost.Python庫,我可以方便地將?C++語言寫的程序庫用于?Python語言,可以用?Python更好地完成更多的任務。
好吧,我承認,我忘了說很重要的一點。那就是,通過?Boost.Python,我們不僅僅可以用?C++來擴展?Python,我們還可以將?Python嵌入?C++。其實?Python運行環境本身就提供了一套嵌入?Python到其它語言的?API,不過是?C語言寫的。有了這套?API,我們就完全可以將?Python嵌入到?C/C++語言程序中去。但是,由于?Python本身是一門面向對象的、動態類型的語言,還帶垃圾收集,而?C是個面向過程的、靜態類型的、不帶垃圾收集的程序設計語言。因此,直接使用這套?C?API非常痛苦。 Boost.Python用面向對象 +模板的方法將這套?C?API重新包裝了一下,我們用起來就清爽多了。不過,目前這個包裝還不完善,因此可能還是需要直接使用一部分?Python?C?API。等它長大了我再來介紹它。
1.1??Boost.Python的特性
目前?Boost.Python 特性包括: o???????????支持?C++引用和指針 o???????????Globally Registered Type Coercions o???????????自動跨模塊類型轉換 o???????????高效的函數重載 o????????????C++異常到?Python異常的轉化 o???????????參數默認值 o???????????關鍵字參數 o???????????在?C++程序中訪問?Python語言中的對象 o???????????導出?C++迭代器為?Python迭代器 o???????????文檔字符串
1.2??跟其它工具的比較
1.3. 進行環境搭建:Boost1.53 可以直接進行exe安裝,省去了編譯的麻煩;官網可下載 boost_1_53_0-msvc-10.0-64.exe
?????????????
2. 建立一個dll工程,命名為例如CSLIC:進行代碼練習
?? 2.1. 從最小的C函數開始
添加包含路徑和庫路徑之后,添加以下包含:
#include <boost/python.hpp> #include <boost/python/module.hpp> #include <boost/python/def.hpp> #include <boost/python/to_python_converter.hpp>void dummyFunc(){cout << "Dummy function called!" << endl; }對應的Wrapper為: BOOST_PYTHON_MODULE(CSLIC) { def(fun, dummyFunc); }這里需要留意的是,對應的MODULE里邊的那個名字必須和 命名為例如CSLIC 里邊制定的庫 名字完全一樣,否則python導入對應的模塊時候會報錯誤。
關于第一次環境搭建,我們需要注意的有四點:
2.2.? 構建類和結構體(一個小例子)
class Complex{public:double real;double imag;Complex(double rp,double ip);double GetArg()const;};使用以下膠水代碼來包裝:class_<Complex>("Complex", init<double,double>()).def_readwrite("real", &Complex::real).def_readwrite("imag", &Complex::imag).def("GetArg", &Complex::GetArg)?? 膠水代碼的意思是,先構造一個臨時對象,該對象的類型是 init<double, double> (模板類 init的一個實例),然后用字符串?"Complex"和這個臨時對象構造另一個臨時對象,該對象的類型是?class_<Complex> (模板類 class_的一個實例)。然后調用第二個臨時對象的?def_readwrite方法,該方法返回這個對象本身,因此可以接著再調用這個對象的?def_readwrite方法和?def方法。
一個完整的例子:
#include<cmath>#include<boost/python.hpp>//包含 Boost.Python的頭文件class Complex { //復數類public:double real; //表示實部的成員double imag; //表示虛部的成員//構造函數,以及初始化列表Complex(double rp,double ip):real(rp), //初始化實部imag(ip) { //初始化虛部}//獲取復數的幅角double GetArg()const{return atan2(imag, real);}};usingnamespace boost::python; // 引入命名空間BOOST_PYTHON_MODULE(CSLIC) {//膠水代碼入口,導出一個名為“CSLIC”的模塊//構造一個類型為 "boost::python::class_<Complex>"的對象 pyComplex//構造參數為字符串 "Complex"//表示要將 C++類 Complex導出到 Python中去,名字也叫 "Complex"class_<Complex> pyComplex("Complex", no_init);//導出它的構造方法,聲明它的構造方法有兩個 double類型的參數pyComplex.def(init<double,double>());//導出它的公有成員 real,//該成員在 Complex類中的位置是 &Complex::real//導出到 Python中之后的名字也是 "real"pyComplex.def_readwrite("real", &Complex::real);//導出它的公有成員 imag,//該成員在 Complex類中的位置是 &Complex::imag//導出到 Python中之后的名字也是 "imag"pyComplex.def_readwrite("imag", &Complex::imag);//導出它的成員方法 GetArg//該方法在 Complex類中的入口是 &Complex::GetArg//導出到 Python中之后的名字也是 "GetArg"pyComplex.def("GetArg", &Complex::GetArg);}
生成動態連接庫 ADT.so (Linux下)或 ADT.dll (Windows下)。然后我可以執行一段?Python腳本來驗證一下:
我遇到的問題:
??? (1):對于函數重載:產生模板庫不能展開問題 ErrorC2784,ErrorC2780
??? 解決方法:消除重載,函數改名......
聲明的時候,則要費時一點:
//helpersbool (X::*fx1)(int) = &X::f;bool (X::*fx2)(int, double) = &X::f;bool (X::*fx3)(int, double, char)= &X::f;int (X::*fx4)(int, int, int) = &X::f;class_<X>("X").def("f", fx1).def("f", fx2).def("f", fx3).def("f", fx4)?
(2):對于不能正常初始化問題:利用WIndepends查看后,缺少兩個com組件;
????????? 打開dll文件,發現:
錯誤: 由于在隱性依賴模塊中丟失導出函數,至少有一個模塊有不能解析的導入。
錯誤: 發現不同 CPU 類型的模塊。
警告: 至少有一個延時加載模塊沒找到。
警告: 由于在延時加載依賴模塊中丟失導入函數,至少有一個模塊具有不能解析的導入。
???? 由于VS對64位os的支持不完善,導致大量使用32位庫,造成不兼容;
??? 解決方法: 切換到32位平臺。
總結
以上是生活随笔為你收集整理的使用boost.python进行混合开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三维建模:方法之CSG与B-Rep比较
- 下一篇: Python中OpenCV2. VS.