如何通过pybind11将C++类的std::vector引用以属性传入Python?
问题原因
你的绑定代码无法生效有两个核心问题:
def_property要求同时传入 getter 和 setter 两个参数,你仅提供了 getter;- 默认情况下 pybind11 会拷贝
std::vector<int>生成 Python list,无法实现 C++ 容器与 Python 对象的双向同步修改。
可行实现方式
方式一:给C++类添加setter成员函数
先修改C++类A,新增用于设置vector的成员函数:
class A { public: std::vector<int>& v() { return m_v; } // 新增setter,用于替换整个vector void set_v(const std::vector<int>& new_v) { m_v = new_v; } // 可选:添加移动语义版本,提升赋值性能 void set_v(std::vector<int>&& new_v) { m_v = std::move(new_v); } private: std::vector<int> m_v; };
再修改pybind11绑定代码,同时传入getter、setter,并指定返回值策略以支持双向同步:
pybind11::class_<A>(m, "A") .def(pybind11::init<>()) .def_property("v", &A::v, &A::set_v, pybind11::return_value_policy::reference_internal );
方式二:不修改C++类,用lambda实现setter
如果不想改动C++代码,可以在绑定阶段用lambda表达式替代setter:
pybind11::class_<A>(m, "A") .def(pybind11::init<>()) .def_property("v", [](A& a) -> std::vector<int>& { return a.v(); }, [](A& a, const std::vector<int>& new_v) { a.v() = new_v; }, pybind11::return_value_policy::reference_internal );
Python端使用效果
完成绑定后,你可以像操作普通Python列表一样使用该属性:
a = A() # 赋值整个vector a.v = [1, 2, 3] # 读取vector内容 print(a.v) # 输出 [1, 2, 3] # 原地修改(如追加元素) a.v.append(4) print(a.v) # 输出 [1, 2, 3, 4]
注意:
return_value_policy::reference_internal是关键,它确保Python端操作的是C++ vector的引用,所有修改会同步到C对象;如果省略该策略,Python得到的是vector的拷贝,修改不会影响C端的原始数据。
内容的提问来源于stack exchange,提问作者jjcasmar
相关产品推荐
相关产品推荐

