C++实现的模块如何提供给Python使用?

C++实现的模块如何提供给Python使用?

安装Python pybind11模块

pip3 install pybind11 -i https://pypi.tuna.tsinghua.edu.cn/simple

编写一个C++程序,以官网示例测试

cat >> example.cpp << EOF
#include 

int add(int i, int j) {
    return i + j;
}

// 模块py绑定,example为我们的模块名,自己定义的,要与so文件名一致,m为模块对象
PYBIND11_MODULE(example, m) {
    // doc是一个注释方法,模块的描述信息
    m.doc() = "pybind11 example plugin"; // optional module docstring
   // 函数定义方法,表示我们绑定上面的函数给Python使用
    m.def("add", &add, "A function that adds two numbers");
}
EOF

注:C++头文件pybind11.h我们没有编译安装源码,而是直接用的pip安装的pybind11。如何配置吗?

cat >> /etc/ld.so.conf.d/py_ext.conf << EOF
# python extend support
/software/py_c_ext/lib/python3.12/site-packages/pybind11/include
EOF
ldconfig

# Python中pybind11路径怎么获取吗?
python3 -m pybind11 --includes
# 然后将输出路径配置到上面文件

编译C++程序

cat >> example.sh << EOF
#!/bin/bash
# c++调用系统默认的C++编译器(通常是g++或clang++)。
# -O3启用最高级别的编译器优化,生成高性能代码(但可能增加编译时间)。
# -Wall启用所有警告信息,帮助捕捉代码中的潜在问题。
# -shared生成动态链接库(.so或.dll),而不是可执行文件。这是Python扩展模块必需的。
# -std=c++11指定使用C++11标准编译代码。
# -fPIC生成位置无关代码(Position Independent Code),这是动态链接库的必要条件。
# $(python3 -m pybind11 --includes)子命令,调用Python获取pybind11的头文件路径。例如,可能输出:-I/usr/include/python3.8 -I/path/to/pybind11/include。
# example.cpp要编译的C++源文件。
# -o example$(python3 -m pybind11 --extension-suffix)指定输出文件名。$(python3 -m pybind11 --extension-suffix) 会返回Python扩展模块的后缀(如.cpython-38-x86_64-linux-gnu.so)。最终输出文件可能是:example.cpython-38-x86_64-linux-gnu.so。
# 关键点
# pybind11的作用: 它是一个轻量级的库,用于将C++代码暴露给Python,自动处理类型转换和模块绑定。
# 动态链接库(-shared): Python需要通过动态库加载C++扩展模块。
# 扩展名后缀: 不同Python版本和操作系统下,扩展模块的后缀不同(如Linux是.so,Windows是.pyd)。pybind11 --extension-suffix会自动适配当前环境。

c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example.so
EOF

Python使用自定义的C++模块

# 我们需要将编译好的so文件复制到Python依赖包目录,当然也可以不移动,但是要将当前目录添加到Python的依赖包遍历列表
mv example.so ../lib/python3.12/site-packages/
# 然后我们使用Python导入模块并调用
python3

>>>import example
>>>example.add(5, 6)
11

你可能感兴趣的:(python,c++,开发语言)