Boost Python重写等于运算符

时间:2015-04-14 05:31:29

标签: python c++ boost boost-python

我试图覆盖我通过boost python公开的类的python相等运算符。

所以我的代码看起来像:

   class_<MyClass, boost::noncopyable, boost::shared_ptr<MyClass> >("MyClass", no_init)
    .def("foo", &MyClass::foo)                                    
     .
     .
     .
    .def("__eq__", &MyClass::operator==) 
    .def("__ne__", &MyClass::operator!=)

然而在python中,当我获取代表相同C ++对象的对象的2个实例,但是从不同的python对象到达时,它们永远不会相等......

因此:

from myPackage import myClass

v1 = myClass.get("abc")
v2 = myClass.get("abc")
if v1 == v2:
   print "true"
else:
   print "false"

始终打印错误。 (为简单起见,我省略了对象的get函数定义)

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

考虑为MyClass::operator==()编写一个C ++测试用例来验证其实现。暴露运算符的Boost.Python代码是正确的。


下面是一个示例demonstrating,将C ++类的比较运算符公开为等式和不等式的富比较方法:

#include <iostream>
#include <string>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>

class foo
{
public:
  foo(const char* value) : value_(value) {}
  foo(const foo&) = delete;
  foo& operator=(const foo&) = delete;

  bool operator==(const foo& rhs) 
  {
    std::cout << "foo::operator==()" << std::endl;
    return value_ == rhs.value_;
  }

  bool operator!=(const foo& rhs)
  {
    std::cout << "foo::operator!=()" << std::endl;  
    return !(*this == rhs);
  }

  std::string get_value() const     { return value_;  }
  void set_value(std::string value) { value_ = value; }

private:
  std::string value_;
};

boost::shared_ptr<foo> make_foo(const char* value)
{
  return boost::make_shared<foo>(value);
}

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<foo, boost::shared_ptr<foo>, boost::noncopyable>(
      "Foo", python::no_init)
    .def("__init__", python::make_constructor(&make_foo))
    .def("__eq__", &foo::operator==)
    .def("__ne__", &foo::operator!=)
    .add_property("value", &foo::get_value, &foo::set_value)
    ;
}

交互式使用:

>>> import example
>>> foo1 = example.Foo("abc")
>>> foo2 = example.Foo("abc")
>>> foo3 = example.Foo("def")
>>> assert(foo1 == foo1)
foo::operator==()
>>> assert(foo1 == foo2)
foo::operator==()
>>> assert(foo1 is not foo2)
>>> assert(foo1 != foo3)
foo::operator!=()
foo::operator==()
>>> foo1.value = foo3.value
>>> assert(foo1 != foo2)
foo::operator!=()
foo::operator==()
>>> assert(foo1 == foo3)
foo::operator==()

如上面的输出所示,C ++比较运算符是从Python调用的。


在示例中,make_foo()工厂函数创建了唯一的C ++ foo实例。因此,我选择将make_foo()包装为构造函数并将其作为__init__方法公开,以隐藏工厂方法的实现细节。如demonstrated here,如果通过静态方法创建对象,仍然可以检查相等性。另一方面,如果像get()这样的静态工厂方法可以返回现有foo实例的句柄,那么可以预期相等和身份比较都可以在Foo Python对象上工作(即{ {1}}。要返回对同一Python对象的引用,需要管理关联的assert(Foo.get("abc") is Foo.get("abc"))

答案 1 :(得分:1)