之前关于Python调用C/C++介绍了:
1.ctypes方式加载并调用C/C++ 动态链接库的方式;
2.使用C/C++编写Python扩展模块的方式。
今天的笔记记录的是使用Boost.Python的方式。
Boost.Python介绍:
Boost.Python是一个开源C++库,它提供了一个简明的IDL式的接口用于绑定C++类和函数到Python。 得益于C++编译期的内部处理(译注:原文是introspection)和最近开发的元编程(metaprogramming)技术,成就了Boost.Python不需引入一种新的语法而只用纯C++的实现。Boost.Python丰富的特性集合以及它的高阶接口使得工程师像混合系统(译注:hybrid system)那样做打包的事情成为可能,并且程序员让在应用C++高效的编译期多态性以及Python非常方便的运行期多态性的时候获得易用性和一致性;
Boost库是非常强大的库, 其中的python库可以用来封装c++被python调用, 功能比较强大, 不但可以封装函数还能封装类, 类成员。
文档:
https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/index.html
前提
使用boost python库需要先进行安装,可能有些版本的操作系统内是有集成的。(例如我使用的Ubuntu16.04)
安装: sudo apt install libboost-python-dev
简单的例子
hello.cpp
#include <boost/python.hpp>
char const* greet()
{
return "hello, world";
}
int add(int x,int y)
{
return x+y;
}
BOOST_PYTHON_MODULE(hello) // 参数hello为模块的名字,没有引号
{
using namespace boost::python;
def("greet", greet); // "greet"是python调的方法名,greet是C++的方法
def("add",add);
}
编译:
g++ -c -fPIC -o hello.o hello.cpp -I /usr/include/python2.7/
g++ -shared -Wl,-soname,hello.so -o hello.so hello.o -L/usr/lib/x86_64-linux-gnu -lpython2.7 -lboost_python
或:
g++ -shared -o hello.so -fPIC hello.cpp -I/usr/include/python2.7/ -lpython2.7 -lboost_python
注意:源代码hello.cpp的位置一定要在声明头文件和链接库的左面(g++自右向左解析)。以下是我趟过的坑:
/*
g++ -fPIC -o hello.so -shared -I/usr/include/python2.7/ -L/usr/lib/x86_64-linux-gnu -lboost_python hello.cpp
编译正常通过,且生成hello.so但是ldd发现没有链接libboost_python这个库的任何信息,import 报错:
'''
ImportError: ./hello.so: undefined symbol: _ZNK5boost6python7objects21py_function_impl_base9max_arityEv
'''
此问题既由于g++语句顺序不当引起,由于gcc/g++语句都由右向左解析,所以如果把源代码放在链接库的右面则有可能链接失败。
另:
如果boost_python库的路径不在ld默认的库中,可以通过-L添加,例如我的libboost_python.so位置在/usr/lib/x86_64-linux-gnu/下:可以通过:-L/usr/lib/x86_64-linux-gnu指定,或添加到/etc/ld.so.conf.d/中并执行ldconfig
*/
脚本编译方式:python setup.py build
setup.py
## python 提供了setup、Extension方法实现编译和模块创建。
#!/usr/bin/env python
from distutils.core import setup
from distutils.extension import Extension
setup(name="hello.test.python",
ext_modules=[
Extension("hello", ["hello.cpp"], ## hello是模块名,hello.cpp是源代码文件
libraries = ["boost_python"]) ## 链接的库
])
测试代码:test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
## 自定义的C++编写的模块
import hello
if __name__ == "__main__":
## 简单的两个测试
print hello.greet()
print hello.add(1,2)
'''
hello, world
3
'''