You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 15:00:49