【问题标题】:pybind11 - Wrapping overloaded assignment operator?pybind11 - 包装重载赋值运算符?
【发布时间】:2023-10-19 14:08:01
【问题描述】:

我正在使用 pybind11 将 C++ 函数公开给 Python 接口。我想包装重载的赋值运算符,但不知道如何。提供的文档和示例并没有真正涵盖它,至少从我所看到的来看。

这是我正在尝试做的简化版本:

class Num{
  public:
    Num(const double& num) : m_val(num), m_type(Num::Type::e_none){}

    Num& operator=(const double& rhs){m_val = rhs;}

  private:
    double m_val;
};

这是包装:

PYBIND11_MODULE(demo, m){
    py::class_<Num>(m, "Num")
        .def(py::init<const double&>())
        // Overloaded assignment operator binding ?
        ;
}

我主要关心的是在将 Num 分配给浮点数时保留它的数据类型。例如:

>>> m = Num(4.5)
>>> type(m)
<class 'demo.Num'>
>>> m = 5.5
>>> type(m)
<class 'float'>

这是我第一次使用 C++ 扩展和绑定,所以任何关于我应该做什么的见解都会很棒!

【问题讨论】:

  • 做不到(好吧,你可以拦截全局字典__setitem__,但这是一个可怕的黑客攻击并且非常脆弱)。问题在于 Python 使用引用赋值,因此没有赋值运算符可以覆盖。具体来说:第二个分配删除了对Num 的旧引用,然后重新分配给5.5。绝不涉及Num 的任何方法。另一种方法是,如果所有 Num 实例都存在于某个类或模块中,那么您可以覆盖该模块/类的 __setitem__
  • 啊,我明白了。因此 Python 创建了一个全新的原生 bool 对象,名称“m”指向该对象,而不是之前创建的 Num 对象。我对弄乱任何 dunder 函数 atm 不感兴趣,但这肯定有很大帮助。谢谢!

标签: python c++ pybind11


【解决方案1】:
.def("assign", &Num::operator=);

详情请咨询https://github.com/pybind/pybind11/issues/250

【讨论】:

  • 这仅适用于 Num& operator=(const Num& ) 函数定义,因此无法处理双重影响。
  • 您可以这样做:.def("assign", py::overload_cast&lt;double&gt;&amp;Num::operator=); 。前提是您有一个带双精度的赋值运算符。或者这个:.def("assign", [](double value, Num&amp; self){self = Num(value)});.