python和c++互操作前面我介紹了一些例子。
系列文章:
Python調用C/C++函數(1)
Python調用採用Boost Python封裝的c++(2)
C++調用Python(3)
C++調用Python(4)
c++和Python互操作進階應用程式(5)
c++調用PythonAPI線程狀態和全域解釋期鎖(6)
因為很容易出問題,比如Unicode的問題,ImportError的問題。所以,把安裝和配置介紹一下。
1.python-dev安裝
http://www.python.org/
下載2.5.1/2.5.2/2.6.1/都可以,3.0沒試過。
需要tk-dev,tcl-dev,zlib
解壓
$./configure --prefix=/home/lhb/local2.5.1 --enable-unicode=ucs4 --enable-shared
enable-unicode:ucs2或者ucs4,linux下一般都是ucs4
enable-shared:編譯出共用庫。
$make
$make install
安裝完畢之後,檢查是否支援ucs4,很多人出現PyUnicode的錯誤,就是因為python沒有支援ucs4
- $ LD_LIBRARY_PATH=/home/lhb/local2.5.1/lib /home/lhb/local2.5.1/bin/python
- Python 2.5.1 (r251:54863, Dec 8 2008, 21:22:27)
- [GCC 4.3.2] on linux2
- Type "help", "copyright", "credits" or "license" for more information.
- >>> import sys
- >>> sys.maxunicode
- 1114111
- >>>
如果顯示是1114111,則是ucs4。
python unicode的文章,可以參考這裡
注意:如果使用新安裝的python,則需要修改環境變數,如 export PYTHONHOME=/home/lhb/local2.5.1/,否則會出現諸如ImportError: /usr/lib/python2.5/lib-dynload/math.so: undefined symbol: PyFPE_jbuf的問題,這個問題的原因就是因為你的python的兩個路徑不一致導致的。
2.boost.python的安裝
可能需要三個包
zlib
http://www.zlib.net/
http://www.zlib.net/zlib-1.2.3.tar.gz
注意,編譯共用庫 ./configure --shared
bzlib
http://www.bzip.org/
http://www.bzip.org/1.0.5/bzip2-1.0.5.tar.gz
libicu
http://www.icu-project.org/download/
boost可以下1_35,1_17版本
http://www.boost.org/
解壓
配置
$./configure --prefix=/home/lhb/local --with-icu --with-libraries=python
with-libraries=python是只編譯python,編譯所有的時間很恐怖的!
$make
$make install
3.例子
- #include <Python.h>
- #include <boost/python.hpp>
- using namespace boost::python;
- char const* greet()
- {
- return "hello, world";
- }
- BOOST_PYTHON_MODULE(hello)
- {
- def("greet", greet);
- }
- int run1()
- {
- Py_Initialize();
- inithello();
- PyRun_SimpleString("import sys");
- PyRun_SimpleString("print sys.version");
- PyRun_SimpleString("print sys.path");
- PyRun_SimpleString("from time import time, ctime");
- PyRun_SimpleString("print 'Today is', ctime(time())");
- PyRun_SimpleString("import hello");
- PyRun_SimpleString("print hello.greet()");
- Py_Finalize();
- return 0;
- }
- int run2()
- {
- Py_Initialize();
- try
- {
- inithello();
- const char* cmd = "import sys/n"/
- "print sys.version/n"/
- "sys.path.append('/home/lhb/local2.5.1/lib/python2.5')/n"/
- "print sys.path/n"/
- "import mytest/n"/
- "mytest.testImport()/n"/
- "from time import time, ctime/n"/
- "print 'Today is', ctime(time())/n"/
- "import hello/n"/
- "print hello.greet()";
- // Retrieve the main module
- object main = import("__main__");
- // Retrieve the main module's namespace
- object global(main.attr("__dict__"));
- // Define the derived class in Python.
- object result = exec(cmd,global,global);
- }
- catch(error_already_set)
- {
- PyErr_Print();
- }
- Py_Finalize();
- return 0;
- }
- int main()
- {
- run1()
- run2()
- }
編譯:
- #!/bin/bash
- boosthead='/home/lhb/local/include/boost-1_37'
- boostlib='/home/lhb/local/lib'
- pythonhead='/home/lhb/local2.5.1/include/python2.5'
- pythonlib='/home/lhb/local2.5.1/lib'
- g++ -o seraph251 seraph.cpp -L${pythonlib} -lpython2.5 -L${boostlib} -lboost_python-mt -I${pythonhead} -I${boosthead} -DARCH32
- #-Xlinker -export-dynamic
- LD_LIBRARY_PATH=${boostlib}:${pythonlib} ldd seraph251
- LD_LIBRARY_PATH=${boostlib}:${pythonlib} ./seraph251
注意:這個選項-Xlinker -export-dynamic,前面配置python的時候enable-shared這個選項,如果沒有寫,則不會編譯出動態庫,只有靜態庫。此時,你寫的例子編譯時間就需要加上-Xlinker -export-dynamic,這個選項,否則,執行時就會出類似下面的問題:ImportError: /usr/lib/python2.5/lib-dynload/time.so: undefined symbol: PyModule_AddObject
注意:很多時候,很多人搞不清楚,python和python-dev以及boost.python的關係。python是執行環境,如果你要c/c++中調用python,或者python調用c或者c++,則需要python-dev。boost.python僅僅是對python-dev進行了封裝,很多函數,兩邊都具有同樣的功能,也就是說用python-dev中的也可以如run1函數,用boost.python中的也行如run2,boost.python的介面封裝得更為友好而已如異常處理。