如何在包装的类中重写__setattr__(来自C ++)? [英] How to override __setattr__ in a wrapped class (from 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屋!