如何在包装的类中重写__setattr__(来自C ++)? [英] How to override __setattr__ in a wrapped class (from C++)?

查看:102
本文介绍了如何在包装的类中重写__setattr__(来自C ++)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用boost::python,我已经能够包装一个具有一些虚函数的类(Node),这是一个麻烦,但是现在我试图覆盖该类的setattr/getattr. 我有boost::python来调用我自己的setattr实现,但是我不知道如何避免发生递归.

Using boost::python, I have been able to wrap a class (Node) which has some virtual functions, and it's been a hoot, but now I'm trying to override setattr/getattr for the class. I've got boost::python to call my own setattr implementation, but I can't figure out how to avoid the recursion that happens.

所以我有一个Node类,并且我希望能够编写:

So I have a Node class, and I want to be able to write:

node1.param1 = 5          # Call node.SetParam
node1.plain_member = 7    # Call object.__setattr__

到目前为止,我(非常删节):

So far, I have (very abridged):

namespace bpy = boost::python;

struct NodeWrap : vcNode, bpy::wrapper<Node> {
  ...  
  static void setattr(bpy::object obj, std::string attr, bpy::object val)
  {
     NodeWrap const& node = bpy::extract<NodeWrap const&>(obj)();
     ParamRef p = node.FindParam(attr);
     if (p)
        py_to_param(p, val); //This part works fine
     else
     {
        obj.attr(attr) = val; //Problematic line - recurses indefinitely
     }
  }
};

然后在BOOST_PYTHON_MODULE部分,我有:

bpy::class_<NodeWrap, boost::shared_ptr<NodeWrap>, boost::noncopyable>("Node")
  ...
  .def("__setattr__". &NodeWrap::setattr);

正如我所说,它可以正常编译,并且可以正确设置任何节点参数",但是如果我尝试设置非参数(例如self.plain_old_member = 7),则会出现递归深度超出"错误,因为我收集到boost::object::attr将调用类的__setattr__方法

As I said, it compiles just fine, and will set any node "params" correctly, but if I try to set a non-param, such as self.plain_old_member = 7 then I get a "Recursion Depth Exceeded" error, because I gather boost::object::attr will call the class' __setattr__ method

在python中,我会通过使用

In python, I would get around this by using

super(Node).__setattr__(self, attr, val)

在问题行中的

,但是我不知道如何从boost :: python做到这一点. 我不介意使用C API(实际上,我尝试使用PyObject_SetAttrString无济于事),但我只是不知道如何从这里到达.

in the problem line, but I can't figure out how to do that from boost::python. I don't mind going to the C API if I have to (in fact, I've tried using PyObject_SetAttrString to no avail), but I just don't know how to get there from here.

干杯, 马特

推荐答案

我相信您想要的Python C-API函数是PyObject_GenericSetAttr;也就是说,您应该将问题线"替换为:

I believe the Python C-API function you want is PyObject_GenericSetAttr; that is, you should replace the "problematic line" with:

bpy::str attr_str(attr);
if (PyObject_GenericSetAttr(obj.ptr(), attr_str.ptr(), val.ptr()) != 0)
    bpy::throw_error_already_set();

我认为这等同于在Python中调用object.__setattr__(self, attr, val),这与在基类上调用__setattr__并不相同,但是区别仅在基类也覆盖了__setattr__时才重要.如果是这样,您需要执行以下操作:

I think this is equivalent to calling object.__setattr__(self, attr, val) in Python, which is not the same as calling __setattr__ on a base class, but the difference only matters if a base class also overrides __setattr__. If that's the case, you'd need to do something like this:

bpy::object cls(bpy::handle<>(PyObject_Type(obj.ptr())));
bpy::object base_cls = cls.attr("__bases__")[0];
base_cls.attr("__setattr__")(obj, attr, val);

这篇关于如何在包装的类中重写__setattr__(来自C ++)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆