当前位置: 首页 > java >正文

三、C++ 的 python 绑定 pybind11

文章目录

  • 一、pybind11 简介
  • 二、实战:使用 pybind11 和 CMake 创建 Python 模块
    • 第 1 步:项目结构
    • 第 2 步:C++ 核心代码
    • 第 3 步:编写绑定代码
    • 第 4 步:配置 CMake
    • 第 5 步:编译与测试


一、pybind11 简介

简介一个只依赖头文件的 C++11 库,让你能用纯 C++ 代码优雅地创建绑定
优点代码极其简洁,与现代 C++ 语法完美融合,自动处理类型转换和引用计数,与 CMake 集成极佳
缺点仅针对 Python,需要支持 C++11 或更高版本的编译器 (小问题)

二、实战:使用 pybind11 和 CMake 创建 Python 模块

 我们的目标是:创建一个 C++ 的 Calculator 类,并将其封装成一个 Python 模块,让我们可以 import 并在 Python 中使用它。

第 1 步:项目结构

 先构建一个结构如下的项目文件夹

calculator_project/
├── CMakeLists.txt              # 主 CMake 配置文件
├── src/
│   ├── calculator.h            # C++ 类的头文件
│   └── calculator.cpp          # C++ 类的实现文件
├── bindings/
│   └── py_bindings.cpp         # 专门用于编写绑定的 C++ 代码
└── test.py                       # 用于测试的 Python 脚本

第 2 步:C++ 核心代码

 这是我们要暴露给 Python 的功能代码。代码位于。

// src/calculator.h
#pragma onceclass Calculator {
private:int last_result_;public:Calculator();void add(int value);void subtract(int value);int getResult() const;
};
// src/calculator.cpp
#include "calculator.h"Calculator::Calculator() : last_result_(0) {}void Calculator::add(int value) {this->last_result_ += value;
}void Calculator::subtract(int value) {this->last_result_ -= value;
}int Calculator::getResult() const {return this->last_result_;
}

第 3 步:编写绑定代码

 这是连接 C++ 和 Python 的桥梁。你只需要用 .def() 来声明要 暴露哪个函数,pybind11 会自动处理参数类型转换、函数调用等所有脏活累活。

// bindings/py_bindings.cpp
#include <pybind11/pybind11.h>
#include "../src/calculator.h" // 包含我们要绑定的 C++ 头文件namespace py = pybind11;// PYBIND11_MODULE 是一个特殊的宏,它会创建 Python 模块的入口点
// 第一个参数 (my_calculator) 是 Python 中 `import` 时使用的模块名
// 第二个参数 (m) 是一个 py::module_ 对象,代表了这个模块本身
PYBIND11_MODULE(my_calculator, m) {// 可选:为模块添加文档字符串m.doc() = "A simple calculator module made with pybind11";// py::class_ 是一个模板,用于将 C++ 类暴露给 Python// 尖括号里是你要绑定的 C++ 类名py::class_<Calculator>(m, "Calculator") // 在 Python 中,这个类的名字将是 "Calculator".def(py::init<>()) // 绑定构造函数。py::init<>() 表示绑定无参构造函数.def("add", &Calculator::add, "Adds a value to the current result") // 绑定 add 方法.def("subtract", &Calculator::subtract, "Subtracts a value") // 绑定 subtract 方法.def("get_result", &Calculator::getResult, "Returns the current result"); // 绑定 getResult 方法
}

第 4 步:配置 CMake

 现在我们用 CMake 把所有东西串起来。这需要你系统上安装了 Python 的开发文件,在 Ubuntu/Debian 上通常是 python3-dev

# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(CalculatorProject)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)# --- 1. 获取 pybind11 ---
# 推荐使用 FetchContent,它会自动下载并配置好 pybind11
include(FetchContent)
FetchContent_Declare(pybind11GIT_REPOSITORY https://github.com/pybind/pybind11.gitGIT_TAG        v2.12.0 # 使用一个稳定版本
)
FetchContent_MakeAvailable(pybind11)# --- 2. 定义我们的 C++ 库 ---
# 把核心逻辑编译成一个静态库,方便管理
add_library(calculator_lib STATIC src/calculator.cpp)
# 确保头文件路径被包含
target_include_directories(calculator_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)# --- 3. 创建 Python 模块 ---
# pybind11_add_module 是 pybind11 提供的 CMake 函数,专门用于创建 Python 扩展模块
# 它会生成一个 .so (Linux) 或 .pyd (Windows) 文件
pybind11_add_module(my_calculator MODULE bindings/py_bindings.cpp)# --- 4. 链接依赖 ---
# 告诉我们的 Python 模块,它需要链接到 calculator_lib 的代码
target_link_libraries(my_calculator PRIVATE calculator_lib)

第 5 步:编译与测试

 现在,标准的 CMake 构建流程即可:

# 1. 创建构建目录并进入
mkdir build
cd build# 2. 运行 CMake 来配置项目
cmake ..# 3. 编译
cmake --build . --config Release

 编译成功后,在 build 目录下,你会找到一个名字类似 my_calculator.cpython-310-x86_64-linux-gnu.so 的文件。这就是我们用 C++ 创建的、货真价实的 Python 模块

 现在,来测试一下。

# 确保你的 python 环境可以找到 build 目录下的模块
# 或者直接在 build 目录下运行 python
import sys
# sys.path.append('./build') # 如果不在 build 目录运行,添加此行try:# 导入我们用 C++ 写的模块!import my_calculatorprint("Successfully imported 'my_calculator'")
except ImportError as e:print(f"Failed to import module: {e}")sys.exit(1)# 创建 Calculator 类的实例,就像它是一个普通的 Python 类
calc = my_calculator.Calculator()
print(f"Initial result: {calc.get_result()}")# 调用它的方法
calc.add(20)
calc.add(5)
print(f"After adding 20 and 5, result is: {calc.get_result()}")calc.subtract(10)
print(f"After subtracting 10, result is: {calc.get_result()}")# 查看文档字符串
print("\nModule docstring:")
print(my_calculator.__doc__)
print("\nClass docstring (default):")
print(my_calculator.Calculator.__doc__)

 运行测试:

# 在项目根目录运行
cd build
python ../test.py

 输出:
在这里插入图片描述

http://www.xdnf.cn/news/15008.html

相关文章:

  • 【C++基础语法】
  • 如何把Arduino IDE中ESP32程序bin文件通过乐鑫flsah_download_tool工具软件下载到ESP32中
  • 【EGSR2025】材质+扩散模型+神经网络相关论文整理随笔(三)
  • SQL 索引与日志知识点详解及练习题​
  • Agent自动化与代码智能
  • HTML应用指南:利用GET请求获取全国永辉超市门店位置信息
  • 申请注册苹果iOS企业级开发者证书需要公司拥有什么规模条件
  • Spring boot整合dubbo+zookeeper
  • 《O-PAS™标准的安全方法》白皮书:为工业自动化系统筑起安全防线
  • Spring核心原理的快速入门:快速了解IoC与DI
  • [实战]调频(FM)和调幅(AM)信号生成(完整C语言实现)
  • 【C++】红黑树的底层思想 and 大厂面试常问
  • selenium跳转到新页面时如何进行定位
  • 【K8S】Kubernetes 使用 Ingress-Nginx 基于 Cookie 实现会话保持的负载均衡
  • 【前端】接口日志追踪
  • OKR工作法
  • x86汇编语言入门基础(三)汇编指令篇3 位移运算
  • Matplotlib-绘制训练曲线指南
  • defer学习指南
  • 黑搜小知识 | DNS域名解析过程是什么样的?
  • 【Modern C++ Part8】Prefer-nullptr-to-0-and-NULL
  • 深度学习12(卷积神经网络)
  • Token 和 Embedding的关系
  • 模型内部进行特征提取时,除了“减法”之外,还有哪些技术
  • SpringCloud系列 - xxl-job 分布式任务调度 (七)
  • Using Spring for Apache Pulsar:Publishing and Consuming Partitioned Topics
  • swiglu 激活函数学习笔记
  • Rust与Cypress应用
  • 技术支持丨解决 ServBay 在 Windows 启动时反复提示安装 .NET 的问题
  • Flask3.1打造极简CMS系统