2

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

所以我有一Node堂课,我希望能够写:

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

到目前为止,我有(非常精简):

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__方法

在 python 中,我会通过使用来解决这个问题

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

在问题行中,但我无法从 boost::python 中弄清楚如何做到这一点。如果必须,我不介意使用 C API(事实上,我尝试过使用PyObject_SetAttrString但无济于事),但我只是不知道如何从这里到达那里。

干杯,马特

4

1 回答 1

1

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

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

我认为这相当于object.__setattr__(self, attr, val)在 Python 中调用,这与调用__setattr__基类不同,但区别仅在基类也覆盖__setattr__. 如果是这种情况,您需要执行以下操作:

bpy::object cls(bpy::handle<>(PyObject_Type(obj.ptr())));
bpy::object base_cls = cls.attr("__bases__")[0];
base_cls.attr("__setattr__")(obj, attr, val);
于 2012-05-23T01:42:01.743 回答