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()";
-
- object main = import("__main__");
-
- object global(main.attr("__dict__"));
-
- 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的接口封装得更为友好而已如异常处理。