pybind11使用指南

结合pybind11官方文档,利用ai整理

pybind11 全面使用指南

Date: October 30, 2025
Code: https://github.com/pybind/pybind11


目录

  1. 概述

  2. 安装指南

  3. 快速开始

  4. 函数绑定

  5. 类绑定

  6. STL容器支持

  7. 高级特性

  8. 跨平台构建

  9. 最佳实践

  10. 常见问题解决


概述

pybind11是一个轻量级的头文件库,用于在C11和Python之间创建无缝的互操作性。它支持将C函数、类和数据结构暴露给Python,反之亦然。

主要特性

  • 头文件库: 无需链接额外的库

  • 跨平台: 支持Windows、Linux、macOS

  • 自动类型转换: 基本数据类型和STL容器的自动转换

  • C++11及以上: 充分利用现代C++特性

  • Python 3.8+: 支持最新的Python版本

支持的编译器

平台 编译器支持 Python版本 特殊要求
Windows MSVC 2022+, Clang, GCC 3.8+ 需要Visual Studio Build Tools
Linux GCC 4.8+, Clang 3.3+ 3.8+ 开发工具链完备
macOS Clang 5.0+ 3.8+ Xcode命令行工具

安装指南

Windows安装

方法1: 使用pip安装

1
pip install pybind11

方法2: 使用conda安装

1
conda install -c conda-forge pybind11

方法3: 源码安装

1
2
3
4
5
6
7
git clone https://github.com/pybind/pybind11.git
cd pybind11
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release
cmake --install .

Linux安装

方法1: 使用包管理器

1
2
3
4
5
6
# Ubuntu/Debian
sudo apt update
sudo apt install pybind11-dev

# Fedora
sudo dnf install pybind11-devel

方法2: 使用pip安装

1
pip install pybind11

方法3: 源码安装

1
2
3
4
5
6
7
git clone https://github.com/pybind/pybind11.git
cd pybind11
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j4
sudo make install

验证安装

1
2
3
4
5
# 检查pybind11版本
python -m pybind11 --version

# 获取头文件路径
python -m pybind11 --includes

快速开始

第一个示例

创建一个简单的C++函数并暴露给Python。

1. 创建C++文件 (example.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
#include <pybind11/pybind11.h>

namespace py = pybind11;

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

PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // 模块文档字符串
m.def("add", &add, "A function that adds two numbers");
}

2. 编译

Linux/macOS:

1
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)

Windows (Visual Studio):

1
cl /O2 /LD /EHsc /I %PYBIND11_INCLUDE% /I %PYTHON_INCLUDE% example.cpp /link /LIBPATH:%PYTHON_LIB% python314.lib /OUT:example.pyd

3. 在Python中使用

1
2
3
import example
print(example.add(1, 2)) # 输出: 3
print(example.__doc__) # 输出: pybind11 example plugin

函数绑定

基本参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <pybind11/pybind11.h>
#include <string>

namespace py = pybind11;

int add(int a, int b) {
return a + b;
}

double multiply(double x, double y) {
return x * y;
}

std::string greet(const std::string& name) {
return "Hello, " + name + "!";
}

PYBIND11_MODULE(example, m) {
m.def("add", &add, "Add two integers");
m.def("multiply", &multiply, "Multiply two doubles");
m.def("greet", &greet, "Greet someone by name");
}

关键字参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <pybind11/pybind11.h>
#include <tuple>

namespace py = pybind11;

std::tuple<int, int, int> create_point(int x, int y, int z) {
return std::make_tuple(x, y, z);
}

PYBIND11_MODULE(example, m) {
m.def("create_point", &create_point,
py::arg("x"), py::arg("y"), py::arg("z"),
"Create a 3D point");

// 简写形式
using namespace pybind11::literals;
m.def("create_point_short", &create_point,
"x"_a, "y"_a, "z"_a,
"Create a 3D point (short notation)");
}

Python使用:

1
point = example.create_point(x=10, y=20, z=30)

默认参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <pybind11/pybind11.h>

namespace py = pybind11;

int power(int base, int exponent = 2) {
int result = 1;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}

PYBIND11_MODULE(example, m) {
m.def("power", &power,
py::arg("base"), py::arg("exponent") = 2,
"Calculate power of a number");
}

Python使用:

1
2
result1 = example.power(5)      # 返回 25 (5^2)
result2 = example.power(5, 3) # 返回 125 (5^3)

禁止类型转换

1
2
3
4
5
6
7
8
9
10
11
12
#include <pybind11/pybind11.h>

namespace py = pybind11;

void strict_int_function(int value) {
// 只接受整数类型
}

PYBIND11_MODULE(example, m) {
m.def("strict_int_function", &strict_int_function,
py::arg("value").noconvert());
}

函数重载

1. 静态类型转换(static_cast)

通过static_cast将成员函数指针转换为特定重载版本的类型,明确指定参数列表,从而绑定目标方法。

1
2
3
py::class_<Pet>(m, "Pet")
.def("set", static_cast<void (Pet::*)(int)>(&Pet::set), "Set the pet's age") // 绑定接受int的版本
.def("set", static_cast<void (Pet::*)(const std::string &)>(&Pet::set), "Set the pet's name"); // 绑定接受string的版本

2. C++14及以上:py::overload_cast(推荐)

对于支持C++14的编译器,可使用py::overload_cast,只需指定参数类型(返回类型和所属类会自动推导),语法更简洁。

1
2
3
py::class_<Pet>(m, "Pet")
.def("set", py::overload_cast<int>(&Pet::set), "Set the pet's age") // 参数为int的版本
.def("set", py::overload_cast<const std::string &>(&Pet::set), "Set the pet's name"); // 参数为string的版本

3. 区分const重载(const与非const版本)

当方法因const限定符重载时(如void func() void func() const),需用py::const_标签区分const版本。

1
2
3
4
5
6
7
8
struct Widget {
int foo(int x, float y); // 非const版本
int foo(int x, float y) const; // const版本
};

py::class_<Widget>(m, "Widget")
.def("foo_mutable", py::overload_cast<int, float>(&Widget::foo)) // 绑定非const版本
.def("foo_const", py::overload_cast<int, float>(&Widget::foo, py::const_)); // 绑定const版本(加py::const_)

4. C++11兼容:py::detail::overload_cast_impl

仅支持C++11的编译器可通过模板别名overload_cast_(基于py::detail::overload_cast_impl)实现类似py::overload_cast的功能,语法稍繁琐。

1
2
3
4
5
6
template <typename... Args>
using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>; // 定义别名

py::class_<Pet>(m, "Pet")
.def("set", overload_cast_<int>()(&Pet::set), "Set the pet's age") // 绑定int版本
.def("set", overload_cast_<const std::string &>()(&Pet::set), "Set the pet's name"); // 绑定string版本

重载构造函数的绑定

对于重载的构造函数,直接多次使用.def(py::init<...>())即可,每次指定不同的参数列表,支持关键字参数和默认参数。

类绑定

基本类绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <pybind11/pybind11.h>
#include <string>
namespace py = pybind11;
class Person {
public:
Person(const std::string& name, int age): name(name), age(age) {}
void set_name(const std::string& new_name) { }
std::string get_name() const { }
int get_age() const { }
std::string greet() const {}
private:
std::string name;
int age;
};

PYBIND11_MODULE(example, m) {
py::class_<Person>(m, "Person")
.def(py::init<const std::string&, int>(), py::arg("name"), py::arg("age"))
.def("set_name", &Person::set_name,py::arg("new_name"))
.def("get_name", &Person::get_name)
.def("get_age", &Person::get_age)
.def("greet", &Person::greet)
.def_property("name",&Person::get_name,&Person::set_name); //该接口将透明调用get set函数

//如果name 和 age为public可以使用如下语法,便于在python中直接访问
def_readwrite("name", &Person::name) // 直接访问成员变量
def_readonly("age", &Person::age); // 只读访问
}

Python使用:

1
2
3
4
5
person = example.Person("Alice", 30)
print(person.get_name()) # Alice
print(person.greet()) # Hello, my name is Alice and I'm 30 years old.
person.set_name("Bob")
print(person.name) # Bob

继承和多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <pybind11/pybind11.h>
#include <string>

namespace py = pybind11;

class Animal {
public:
virtual ~Animal() {}
virtual std::string speak() const = 0;
virtual int get_legs() const = 0;
};

class Dog : public Animal {
public:
std::string speak() const override {return "Woof!";}
int get_legs() const override { return 4; }
void fetch() const {// 狗特有的方法}
};

class Bird : public Animal {
public:
std::string speak() const override {return "Chirp!";}
int get_legs() const override {return 2;}
void fly() const {// 鸟特有的方法}
};
//如果基类中包含纯虚函数,则不能将其与py::init<...>()绑定
PYBIND11_MODULE(example, m) {
py::class_<Animal>(m, "Animal")
.def("speak", &Animal::speak)
.def("get_legs", &Animal::get_legs);

py::class_<Dog, Animal>(m, "Dog")
.def(py::init<>())
.def("fetch", &Dog::fetch);

py::class_<Bird, Animal>(m, "Bird")
.def(py::init<>())
.def("fly", &Bird::fly);
}

虚函数重写(蹦床类)

见另一份指南


STL容器支持

基础容器转换

pybind11通过pybind11/stl.h头文件提供STL容器的自动转换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
#include <map>
#include <set>
#include <string>

namespace py = pybind11;

// 向量处理
std::vector<int> process_vector(const std::vector<int>& input) {
std::vector<int> result;
for (int num : input) {
result.push_back(num * 2);
}
return result;
}

// 集合处理
std::set<std::string> unique_words(const std::vector<std::string>& words) {
return std::set<std::string>(words.begin(), words.end());
}

// 字典处理
std::map<std::string, int> count_chars(const std::string& str) {
std::map<std::string, int> result;
for (char c : str) {
result[std::string(1, c)]++;
}
return result;
}

PYBIND11_MODULE(example, m) {
m.def("process_vector", &process_vector, "Double each element in vector");
m.def("unique_words", &unique_words, "Get unique words from list");
m.def("count_chars", &count_chars, "Count character occurrences");
}

Python使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
import example

# 向量处理
result = example.process_vector([1, 2, 3, 4])
print(result) # [2, 4, 6, 8]

# 集合处理
unique = example.unique_words(["apple", "banana", "apple", "orange"])
print(unique) # {'apple', 'banana', 'orange'}

# 字典处理
counts = example.count_chars("hello world")
print(counts) # {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}

嵌套容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
#include <map>
#include <set>
#include <string>

namespace py = pybind11;

// 向量中的映射
std::vector<std::map<std::string, int>> process_nested_data(
const std::vector<std::map<std::string, int>>& data) {

std::vector<std::map<std::string, int>> result;
for (const auto& map_data : data) {
std::map<std::string, int> processed_map;
for (const auto& [key, value] : map_data) {
processed_map[key] = value * 2;
}
result.push_back(processed_map);
}
return result;
}

// 复杂嵌套结构
std::map<std::string, std::vector<std::set<int>>> complex_structure() {
return {
{"even", {{2, 4, 6}, {8, 10, 12}}},
{"odd", {{1, 3, 5}, {7, 9, 11}}}
};
}

PYBIND11_MODULE(example, m) {
m.def("process_nested_data", &process_nested_data, "Process nested data structures");
m.def("complex_structure", &complex_structure, "Create complex nested structure");
}

C++17容器支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <optional>
#include <variant>
#include <string>

namespace py = pybind11;

// std::optional示例
std::optional<int> find_first_even(const std::vector<int>& numbers) {
for (int num : numbers) {
if (num % 2 == 0) {
return num;
}
}
return std::nullopt;
}

// std::variant示例
using Value = std::variant<int, double, std::string>;

std::string value_type(const Value& value) {
return std::visit([](auto&& arg) -> std::string {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>)
return "integer";
else if constexpr (std::is_same_v<T, double>)
return "double";
else if constexpr (std::is_same_v<T, std::string>)
return "string";
else
return "unknown";
}, value);
}

PYBIND11_MODULE(example, m) {
m.def("find_first_even", &find_first_even, "Find first even number");
m.def("value_type", &value_type, "Get type of variant value");
}

高级特性

异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <pybind11/pybind11.h>
#include <stdexcept>
#include <string>

namespace py = pybind11;

int divide(int a, int b) {
if (b == 0) {
throw std::runtime_error("Division by zero is not allowed");
}
return a / b;
}

void validate_age(int age) {
if (age < 0) {
throw std::invalid_argument("Age cannot be negative");
}
if (age > 150) {
throw std::out_of_range("Age is too large");
}
}

PYBIND11_MODULE(example, m) {
m.def("divide", &divide, "Divide two integers");
m.def("validate_age", &validate_age, "Validate age range");
}

Python中处理异常:

1
2
3
4
5
6
7
8
9
10
11
import example

try:
result = example.divide(10, 0)
except RuntimeError as e:
print(f"Error: {e}") # Error: Division by zero is not allowed

try:
example.validate_age(-5)
except ValueError as e:
print(f"Validation error: {e}")

自定义类型转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <string>

namespace py = pybind11;

// 自定义数据结构
struct Point {
int x;
int y;

Point(int x_ = 0, int y_ = 0) : x(x_), y(y_) {}

Point operator+(const Point& other) const {
return Point(x + other.x, y + other.y);
}

std::string to_string() const {
return "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
}
};

// 自定义类型转换器
namespace pybind11 { namespace detail {
template <> struct type_caster<Point> {
public:
PYBIND11_TYPE_CASTER(Point, _("Point"));

// 从Python对象转换到C++
bool load(handle src, bool) {
if (!src) return false;
auto obj = reinterpret_borrow<dict>(src);
value.x = obj["x"].cast<int>();
value.y = obj["y"].cast<int>();
return true;
}

// 从C++转换到Python对象
static handle cast(Point src, return_value_policy /* policy */, handle /* parent */) {
dict d;
d["x"] = src.x;
d["y"] = src.y;
return d.release();
}
};
}}

PYBIND11_MODULE(example, m) {
py::class_<Point>(m, "Point")
.def(py::init<int, int>(), py::arg("x") = 0, py::arg("y") = 0)
.def("__add__", &Point::operator+)
.def("to_string", &Point::to_string)
.def_readwrite("x", &Point::x)
.def_readwrite("y", &Point::y);
}

NumPy集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <vector>

namespace py = pybind11;

// 将std::vector转换为NumPy数组
py::array_t<double> vector_to_numpy(const std::vector<double>& vec) {
return py::array_t<double>(vec.size(), vec.data());
}

// 从NumPy数组创建std::vector
std::vector<double> numpy_to_vector(const py::array_t<double>& array) {
std::vector<double> result(array.size());
std::memcpy(result.data(), array.data(), array.size() * sizeof(double));
return result;
}

// 就地修改NumPy数组
void multiply_array_inplace(py::array_t<double>& array, double factor) {
py::buffer_info buf = array.request();
double* ptr = static_cast<double*>(buf.ptr);

for (size_t i = 0; i < buf.size; i++) {
ptr[i] *= factor;
}
}

PYBIND11_MODULE(example, m) {
m.def("vector_to_numpy", &vector_to_numpy, "Convert vector to NumPy array");
m.def("numpy_to_vector", &numpy_to_vector, "Convert NumPy array to vector");
m.def("multiply_array_inplace", &multiply_array_inplace, "Multiply array elements in-place");
}

嵌入Python解释器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <pybind11/embed.h>
#include <iostream>
#include <string>

namespace py = pybind11;

int main() {
// 启动Python解释器
py::scoped_interpreter guard{};

// 执行Python代码
py::print("Hello from embedded Python!");

// 导入模块
py::module_ math = py::module_::import("math");
py::object result = math.attr("sqrt")(25);
std::cout << "Square root of 25 is " << result.cast<double>() << std::endl;

// 执行Python字符串
py::exec(R"(
def add(a, b):
return a + b

result = add(3, 5)
print(f"3 + 5 = {result}")
)");

// 创建嵌入式模块
PYBIND11_EMBEDDED_MODULE(fast_ops, m) {
m.def("multiply", [](int a, int b) {
return a * b;
});
}

auto fast_ops = py::module_::import("fast_ops");
int product = fast_ops.attr("multiply")(4, 6).cast<int>();
std::cout << "4 * 6 = " << product << std::endl;

return 0;
}

跨平台构建

CMake配置

见另一份指南

命令行编译

Linux/macOS

1
2
3
4
5
6
7
8
9
10
11
12
# 创建构建目录
mkdir build
cd build

# 配置CMake
cmake .. -DCMAKE_BUILD_TYPE=Release

# 编译
make -j4

# 安装
sudo make install

Windows (Visual Studio)

1
2
3
4
5
6
7
8
9
10
11
12
# 创建构建目录
mkdir build
cd build

# 配置CMake (64位)
cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release

# 编译
cmake --build . --config Release --target ALL_BUILD

# 安装
cmake --build . --config Release --target INSTALL

setuptools配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# setup.py
from setuptools import setup, Extension
from pybind11.setup_helpers import Pybind11Extension, build_ext
import sys

ext_modules = [
Pybind11Extension(
"my_module",
["src/main.cpp", "src/utils.cpp"],
include_dirs=["include"],
extra_compile_args=["-std=c++17"],
language="c++",
),
]

setup(
name="my_module",
version="1.0.0",
author="Your Name",
author_email="your.email@example.com",
description="A pybind11 example module",
long_description="",
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext},
zip_safe=False,
python_requires=">=3.8",
)

使用setup.py构建:

1
python setup.py build_ext --inplace

绑定代码分离

将C++实现和pybind11绑定代码分离:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// src/core.h (纯C++接口)
#pragma once
#include <vector>
#include <string>

namespace my_module {
std::vector<double> process_data(const std::vector<double>& input);
std::string format_result(double value);
}

// src/core.cpp (C++实现)
#include "core.h"
#include <algorithm>

namespace my_module {
std::vector<double> process_data(const std::vector<double>& input) {
std::vector<double> result = input;
std::transform(result.begin(), result.end(), result.begin(),
[](double x) { return x * 2.0; });
return result;
}

std::string format_result(double value) {
return "Result: " + std::to_string(value);
}
}

// src/bindings.cpp (pybind11绑定)
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "core.h"

namespace py = pybind11;

PYBIND11_MODULE(my_module, m) {
m.doc() = "My module documentation";

m.def("process_data", &my_module::process_data,
"Process input data");

m.def("format_result", &my_module::format_result,
"Format result as string");
}

常见问题解决

1. 编译错误

问题:头文件找不到

1
fatal error: pybind11/pybind11.h: No such file or directory

解决方案:

1
2
3
4
5
# 方法1: 使用pip安装的pybind11
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)

# 方法2: 指定头文件路径
c++ -O3 -Wall -shared -std=c++11 -fPIC -I/path/to/pybind11/include example.cpp -o example.so

问题:Python版本不匹配

1
undefined symbol: PyExc_RuntimeError

解决方案:
确保使用的Python版本与编译时使用的版本一致。

1
2
3
4
5
6
# 检查Python版本
python3 --version

# 使用正确的Python配置
python3-config --includes
python3-config --extension-suffix

2. 运行时错误

问题:模块导入失败

1
ImportError: No module named 'example'

解决方案:

1
2
3
4
5
6
7
8
# 检查模块文件是否存在
ls -la example*

# 检查Python路径
python3 -c "import sys; print(sys.path)"

# 将模块所在目录添加到Python路径
export PYTHONPATH=$PYTHONPATH:/path/to/module

问题:类型转换错误

1
TypeError: incompatible types, c++ type is std::vector<int>

解决方案:
确保包含STL头文件:

1
#include <pybind11/stl.h>

3. 性能问题

问题:大数据传输缓慢

解决方案:
使用NumPy数组避免数据拷贝:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <pybind11/numpy.h>

py::array_t<double> process_large_data(py::array_t<double>& input) {
py::buffer_info buf = input.request();
double* ptr = static_cast<double*>(buf.ptr);

// 就地处理数据
for (size_t i = 0; i < buf.size; i++) {
ptr[i] = ptr[i] * 2.0;
}

return input;
}

4. 跨平台问题

问题:Windows上链接错误

1
error LNK2001: unresolved external symbol

解决方案:
使用正确的Visual Studio版本和架构:

1
2
3
4
5
# 使用x64架构
cmake .. -G "Visual Studio 17 2022" -A x64

# 确保使用与Python匹配的架构
python -c "import platform; print(platform.architecture())"

问题:macOS上符号冲突

解决方案:
使用dynamic_lookup:

1
2
3
if(APPLE)
target_link_options(example PRIVATE -undefined dynamic_lookup)
endif()

5. 调试技巧

启用调试信息

1
2
3
4
5
6
# Linux/macOS
cmake .. -DCMAKE_BUILD_TYPE=Debug
make

# Windows
cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Debug

使用GDB调试

1
2
3
4
gdb python3
(gdb) run -c "import example; example.add(1, 2)"
(gdb) break example.cpp:10
(gdb) continue

输出调试信息

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <pybind11/pybind11.h>
#include <iostream>

namespace py = pybind11;

int add(int a, int b) {
std::cout << "Adding " << a << " and " << b << std::endl;
return a + b;
}

PYBIND11_MODULE(example, m) {
m.def("add", &add);
}