boost.python入門教程 ----python 嵌入c++
http://www.cnblogs.com/rocketfan/archive/2009/11/15/1603400.html
boost.python 中 python 嵌入c++ 部分,網上找到的中文資料似乎都有些過時了,
如 boost.python學習筆記 http://edyfox.codecarver.org/html/boost_python.html
在boost.python版本2中,提供更加簡潔易用的介面,我們可以使用從而
代替原始的PyRun_SimpleString等等python c 轉換api.
關於python與C++混合程式設計,事實上有兩個部分
- extending 所謂python 程式中呼叫c/c++程式碼, 其實是先處理c++程式碼, 預先生成的動態連結庫, 如example.so, 而在python程式碼中import example;即可使用c/c++的函式 .
- embedding c++程式碼中呼叫 python 程式碼.
兩者都可以用 python c 轉換api,解決,具體可以去python官方文件查閱,但是都比較繁瑣.
對於1,extending,常用的方案是boost.python以及swig.
swig是一種膠水語言,粘合C++,PYTHON,我前面的圖形顯示二叉樹的文章中提到的就是利用pyqt作介面,
呼叫c++程式碼使用swig生成的.so動態庫.
而boost.python則直接轉換,可以利用py++自動生成需要的wrapper.關於這方面的內容的入門除了boost.python
官網,中文的入門資料推薦
http://www.cppblog.com/skyscribe/archive/2009/08/09/92686.html
一共3個系列吧,他的部落格上還有cmake的內容,本文的環境也將使用cmake編譯,可供參考.
對於2 似乎swig就不提供支援了,swig 不僅僅支援 python呼叫c/c++,還支援許多其它高階語言呼叫c++, 但是它不支援python 嵌入c++.
下面僅僅介紹2 embedding, 事實上embedding 比 extending 簡單的多:)
本將會給出具體例項程式碼以及環境配置方法.有些只是為了簡單,並不是最好的配置方案,
如cmake的使用.
- 環境配置
我的工作環境是ubuntu8.04,gcc4.24,cmake2.6,boost1.4,python2.6.
如果你在windows下工作就不用往下看了.
boost.python似乎還不支援python3 所以個人推薦使用python2.6,當然ubuntu8.04自帶的python2.5
也可以的.
1.python2.6 的安裝
去官網下載python2.6,解壓縮,
./configure --enable-shared;make; sudo make install
標頭檔案應該會預設安裝到/usr/local/include/python2.6.
注意第一步 ./configure --help可以檢視幫助選項,如你想設定安裝到什麼路徑,
特別注意 --enable-shared選項生成動態連結庫,libpython2.6.so
這個是我們下面需要的一定要有這個選項! 預設會生成到/usr/local/lib下,你直接./configure
的話則不會生成動態連結庫.
2. cmake 安裝
sudo apt-get insall cmake即可,也可以去官網下載安裝最新的cmake2.8
3. boost 安裝
去官網下載boost.1.4.2 解壓縮
./bootstrap.sh --help
./bootstrap.sh --show-libraries #會顯示你有哪些庫可以安裝
這裡解釋一下,因為boost是模板庫,很多都只需要標頭檔案,不需要編譯安裝,但是有些庫是需要安裝的如
regex,python, 等等,你可以檢視一下選擇自己需要安裝的庫.
我選擇了全部安裝,預設是全部安裝.
./bootstrap.sh --prefix=/usr/local/boost1.4
這樣會將標頭檔案安裝到 /usr/local/boost1.4/include
庫檔案安裝到 /usr/local/boost1.4/lib
然後
./bjam install
注意不加install的話檔案不會拷貝到你指定的安裝路徑的.
然後你可以設定一下環境變數,如BOOST_ROOT,BOOST_LIB
下面我實驗的時候直接寫的安裝路徑,如 /usr/local/boost1.4/include
- 直接用python,c 轉換api 如何實現.
看一個最簡單的例子
#include <Python.h>intmain(int argc, char*argv[])
{
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n""print 'Today is',ctime(time())\n");
Py_Finalize();
return0;
}
假設這個程式命名為a.cc,如何編譯它呢.無外乎要能找到python的標頭檔案和動態連結庫.如下:
g++ -I /usr/local/include/python2.6 -lpython2.6 -o a a.cpp
./a
Today is Sun Nov 15 17:25:25 2009
- boost.python的支援
使用boost.python需要以下步驟
- #include <boost/python.hpp>
- 呼叫Py_Initialize() 來開啟直譯器 並且生成 _main_ 模組 .
- 使用該直譯器呼叫 Python C API .注意當前你一定不要最後呼叫Py_Finalize了結束直譯器 ,這個問題可能會在以後版本中改掉. 當然你可以在這些步驟中有其它的C++程式碼.
eval, exec, exec_file,
分別對應
計算表示式值,
執行python語句,
執行python 文字如a.py.
而boost::python::object的使用,使得呼叫python中的函式異常的簡單.
下面的程式碼,演示了exec,exec_file,object的使用,基本上覆蓋了所有常見的需求.
首先寫一個簡單的python 檔案 ,
simple.py
def foo(i =4):return i +2008
寫一個C++的程式碼
embedding.cc
#include <iostream>usingnamespace std;#include <boost/python.hpp>usingnamespace boost::python;
int main(int argc, char*argv[])
{
Py_Initialize();
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
exec("hello = file('hello.txt', 'w')\n""hello.write('Hello world!')\n""hello.close()",
main_namespace);
exec("result = 5 ** 2", main_namespace);
int five_squared = extract<int>(main_namespace["result"]);
cout <<"The five_squeared caculated by python is "<< five_squared << endl;
// Load the sys module.object sys = import("sys");
// Extract the python version. std::string version = extract<std::string>(sys.attr("version"));
std::cout << version << std::endl;
//要求simple.py與可執行檔案在相同路徑下! 執行okobject simple = exec_file("simple.py",main_namespace, main_namespace);
//dict global;
//object result = exec_file("simple.py", global, global);object foo = main_namespace["foo"];
int val = extract<int>(foo(5));
cout <<"Python has caculated foo as "<< val << endl;
return0;
}
如何編譯這個程式呢,其實就是能找的python, 以及boost.python的標頭檔案和庫檔案.我採用了cmake,管理.
最簡單的在相同程式碼路徑下,建立一個檔案CMakeLists.txt,寫入以下內容,注意你可能需要根據自己的安裝路徑進行
更改.
project(Embedding) #隨便起一個工程名稱
#boost.python,python標頭檔案路徑
include_directories(/usr/local/boost1.4/include /usr/local/include/python2.6)
link_directories(/usr/local/boost1.4/lib /usr/local/lib) #boost.python,python動態連結庫路徑
add_executable (embedding embedding.cc) #原始檔embedding.cc 生成可執行檔案embedding
target_link_libraries(embedding libboost_python.so libpython2.6.so) #可執行檔案依賴與這兩個庫
如果你配置好環境變數,或者標頭檔案庫在預設的查詢位置,或者應用ln可能不需要這麼繁瑣,但是這樣是一個可行的方案.
cmake .
make
./embedding
The five_squeared caculated by python is 25
2.6.2 (r262:71600, Nov 14 2009, 14:18:33)
[GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu4)]
Python has caculated foo as 2013