【问题标题】:Using Boost Python, I can wrap C++ overloaded operators "+=", "-=", "*=", but not "/="?使用 Boost Python,我可以包装 C++ 重载运算符“+=”、“-=”、“*=”,但不能包装“/=”?
【发布时间】:2021-05-12 12:15:10
【问题描述】:

Boost Python 有一个非常简单的方法来包装重载运算符。 boost.org (https://www.boost.org/doc/libs/1_66_0/libs/python/doc/html/tutorial/tutorial/exposing.html) 上公开 C++ 类、方法等的教程给出了这个例子:

示例类 FilePos 的重载 C++ 运算符:

class FilePos { /*...*/ };

FilePos     operator+(FilePos, int);
FilePos     operator+(int, FilePos);
int         operator-(FilePos, FilePos);
FilePos     operator-(FilePos, int);
FilePos&    operator+=(FilePos&, int);
FilePos&    operator-=(FilePos&, int);
bool        operator<(FilePos, FilePos);

如何将它们映射到 Python:

class_<FilePos>("FilePos")
    .def(self + int())          // __add__
    .def(int() + self)          // __radd__
    .def(self - self)           // __sub__
    .def(self - int())          // __sub__
    .def(self += int())         // __iadd__
    .def(self -= other<int>())
    .def(self < self);          // __lt__

我有一个名为“Angle”的 C++ 类,它代表一个角度。它具有重载的运算符,包括“+=”、“-=”、“*=”和“/=”。每个重载运算符都旨在将某些 double 类型的输入与 Angle 类所持有的度数相加、减、乘或除。 Angle 类包装器以与上面示例中描述的完全相同的方式映射这些重载运算符。当我在 Python 中测试加法、减法和乘法运算符时,它们工作得非常好。除法运算符,并非如此。当我像这样运行一个简单的测试时:

A = Angle(1) # instantiate Angle object with magnitude of 1 radian
A /= 2.0 # attempt to divide the radian measurement by 2

我收到以下错误:

TypeError: unsupported operand type(s) for /=: 'Angle' and 'float'

基于这个问题:

Error when trying to overload an operator "/"

我看到 Python3(我正在使用的版本)对“/”字符有一种独特的理解方式。但是,这个解决方案对我不起作用,因为我使用的类是一个封装的 C++ 类。

我的问题:有没有办法使用 boost 以保留相同语法的方式将重载的运算符“/=”从 C++ 映射到 python(即不在 C++ 中编写一个名为“selfdiv”的瘦包装器来执行相同的操作,但必须用“Angle.selfdiv()”调用)?也许某种方式可以覆盖 Python 解释该正斜杠字符的方式?

【问题讨论】:

  • 你试过A /= Angle(2);吗?

标签: python c++ boost


【解决方案1】:

Python 3 改变了除法运算符的定义方式,Boost.Python 的自动生成版本使用旧的 Python 2 样式进行就地除法,这不再有效。这似乎是一个疏忽,因为非就地版本已更新为 Python 3 的 __truediv__ 魔术方法。关于这件事有一个open GitHub issue。在它得到修复之前,您可以像定义任何其他类成员函数一样定义 __itruediv__ 和/或 __ifloordiv__

class_<Foo>("Foo")
    .def(
        "__itruediv__",
        &Foo::operator/=,
        return_self<>{}
    );

【讨论】:

  • 对我来说效果很好,逐字有效地实现了您的建议,操作员在 python 中按预期执行。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2017-10-30
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
  • 1970-01-01
  • 2012-04-23
  • 2017-05-24
相关资源
最近更新 更多