Pybind11调用C++指针参数函数时Python与C++端地址不一致如何解决
问题根因
两端地址不匹配的核心原因是 pybind11不会将Python传入的整数值默认解析为原生内存指针:
- 你在绑定代码中将入参声明为
double*,Python侧传入的ptr_addressof本质是Python int类型的地址数值,pybind11会对这个参数做隐式转换:把传入的整数值转成double类型存入临时栈内存,再把这块临时内存的地址传给C++函数。 - C++端打印的是临时变量的栈地址,和ctypes分配的
c_double对象的内存地址完全无关,自然无法匹配。
可直接运行的修复方案
只需要修改两处:一是调整pybind绑定层的参数类型,手动做地址到指针的转换,绕过pybind的默认隐式转换逻辑;二是Python侧直接传入ctypes拿到的整数值地址即可。
修改后的C++/pybind绑定代码
#include <pybind11/pybind11.h> #include <cstdint> #include <iostream> // 原C++函数不需要做任何修改 void myFunc(double* ptr, double value) { *ptr = value; std::cout << "ptr value:\t\t" << *ptr << std::endl; std::cout << "ptr address:\t\t" << ptr << std::endl; } PYBIND11_MODULE(test_bind, m) { m.def("myFunc", [](uintptr_t ptr_addr, double value) { // 直接将地址数值强转为目标指针类型,跳过pybind默认转换 double* target_ptr = reinterpret_cast<double*>(ptr_addr); myFunc(target_ptr, value); }, "pointer pass test function"); }
这里用uintptr_t承接地址值是跨平台兼容的标准写法,不会在32/64位系统上出现地址截断问题。
修改后的Python调用代码
import ctypes from test_bind import myFunc ptr_value = ctypes.c_double() ptr_address = ctypes.addressof(ptr_value) print(f'Python side ptr address:\t{ptr_address:#x}') test_val = 14.0 myFunc(ptr_address, test_val) # 验证值是否正确写入原内存 print(f"Python side readback value:\t{ptr_value.value}")
预期运行输出
运行后可以看到两端地址完全一致,值也能正确回读:
Python side ptr address: 0x219d1d7f010 ptr value: 14 ptr address: 0x219d1d7f010 Python side readback value: 14.0
注意事项
- 不要直接在pybind绑定层暴露裸指针类型(比如
double*)给Python侧传参:pybind11仅对numpy数组、自身封装的自定义类型等特定对象做正确的内存地址映射,对裸整数、原生ctypes对象默认不会透传原始地址。 - 传入的内存地址必须指向合法内存,且内存生命周期覆盖整个C++函数调用周期,避免传已被GC回收的对象地址触发段错误。
- 如果需要传递其他类型的指针,只需要修改
reinterpret_cast的目标类型即可,逻辑完全通用。
内容的提问来源于stack exchange,提问作者Nova
相关产品推荐
相关产品推荐

