很久没有更新文章了,今天把近期使用C++封装Python扩展模块的经验做一个系统整理。在实际开发中,经常需要将C++代码包装成Python模块,经过多种方案对比,最终还是觉得boost.python最为顺手。不过网上许多教程描述不够清晰,新手特别容易掉进各种坑里。这里分享一个成功的实战案例,并详细解析那些容易让人困惑的细节,帮助你快速掌握C++编写Python扩展的技巧。

boost.python入门
概述与优势
用C++编写Python扩展模块有多种实现方式,选择boost.python的原因在于它相对简洁,只需编写少量胶水代码,就能把更多精力集中在C++核心逻辑上。关于boost.python的具体背景这里不再展开,感兴趣的朋友可以自行搜索了解更多。
安装方法
这里主要介绍Ubuntu系统下的安装方式:
sudo apt-get install libboost-all-dev
# 或者
sudo apt-get install libboost-python-dev
# 此方式未经验证,读者可自行尝试
通过源码安装也是可行的,但需要提前配置好环境变量,否则编译时容易出错。当然,你也可以在编译时直接指定所需的路径。
实例演示
C++ 代码详解
下面这个示例重点说明了容易混淆的地方,帮助你避开常见陷阱。
#include
#include
#include // 必须引入这个头文件
using namespace boost::python;
class HelloWorld {
public:
HelloWorld(const std::string& name, int age);
void printInfo();
private:
std::string m_name;
int m_age;
};
HelloWorld::HelloWorld(const std::string& name, int age) : m_name(name), m_age(age) {}
void HelloWorld::printInfo() {
std::cout << "我叫" << m_name << ", " << m_age << "岁了" << std::endl;
}
void ceshi() {
std::cout << "ceshi" << std::endl;
}
BOOST_PYTHON_MODULE(helloworld) {
// 类导出成Python可调用的动态链接库的方式
class_("helloworld", init())
.def("printinfo", &HelloWorld::printInfo);
// 普通函数导出成Python可调用的动态链接库的方式
def("ceshi", &ceshi);
}
编译命令说明
以下命令用于生成动态链接库,请根据实际环境调整参数。
# python3
g++ -shared -o helloworld.so -fPIC -I/usr/include/python3.6m/ helloworld.cpp -lpython3.6m -lboost_python3
# python2
g++ -shared -o helloworld.so -fPIC -I/usr/include/python2.7/ helloworld.cpp -lpython -lboost_python
参数含义解析
-shared:指示编译器生成动态链接库。-o:指定输出文件名称。-fPIC:生成位置无关代码,这是动态库必须的选项。-I(大写的i):将后面的目录添加到头文件搜索路径中。-l:指定要链接的库名称。
如果编译过程没有报错,当前目录下会生成一个名为helloworld.so的动态链接库文件。你可以直接在当前目录下进入Python Shell进行测试,也可以将该文件放入Python的site-packages目录,这样在任何位置都能导入使用。
测试验证
>>> import helloworld
>>> hw = helloworld.helloworld("lanyulei", 18)
>>> hw.printinfo()
我叫lanyulei, 18岁了
如果文章中仍有不足之处,欢迎指出,我会尽快修正,感谢你的阅读。
