首页 > 解决方案 > boost::python:如何覆盖静态属性?

问题描述

我有一个基类和一个派生类,它们都有一个同名的静态方法。是否可以在保持名称相同的同时公开它们?这会编译,但在导入模块时会引发异常。

struct Base
{
    static std::string say_hi() { return "Hi"; }
};

struct Derived : public Base
{
    static std::string say_hi() { return "Hello"; }
};

BOOST_PYTHON_MODULE(HelloBoostPython)
{
    namespace py = boost::python;

    py::class_<Base>("Base").add_static_property("say_hi", &Base::say_hi);

    py::class_<Derived, py::bases<Base>>("Derived").add_static_property("say_hi", &Derived::say_hi);
}

导入时:

>>> import HelloBoostPython
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
SystemError: initialization of HelloBoostPython raised unreported exception

将最后一行更改为不同的名称是可行的,但我宁愿覆盖基类的属性:

py::class_<Derived, py::bases<Base>>("Derived").add_static_property("say_hello", &Derived::say_hi);

这有效,但我得到类方法而不是属性:

BOOST_PYTHON_MODULE(HelloBoostPython)
{
    namespace py = boost::python;

    py::object base = py::class_<Base>("Base");
    base.attr("say_hi") = Base::say_hi;

    py::object derived = py::class_<Derived, py::bases<Base>>("Derived");
    derived.attr("say_hi") = Derived::say_hi;
}

这将为我提供属性,但如果静态方法不是常量,则在一般情况下不起作用:

BOOST_PYTHON_MODULE(HelloBoostPython)
{
    namespace py = boost::python;

    py::object base = py::class_<Base>("Base");
    base.attr("say_hi") = Base::say_hi();

    py::object derived = py::class_<Derived, py::bases<Base>>("Derived");
    derived.attr("say_hi") = Derived::say_hi();
}

标签: pythonc++boost-python

解决方案


问题在于,当 Boost.Python 的元类尝试声明和设置Derived.say_hi时,它解析为,Base.say_hi.__set__因为它是一个现有的类描述符,继承自Base. 一个解决方案可能是自己将属性绑定到您的Derived类。例如

namespace py = boost::python;

py::class_<Base>("Base").add_static_property("say_hi", &Base::say_hi);

py::class_<Derived, py::bases<Base>> Derived_("Derived");

PyDict_SetItemString(
    py::downcast<PyTypeObject>(Derived_.ptr())->tp_dict,
    "say_hi",
    Derived_.attr("__base__").attr("__dict__")["say_hi"].attr("__class__")(
        py::make_function(&Derived::say_hi)
    ).ptr()
);

这种方式say_hi直接绑定到Derived类作为Boost.Python.StaticProperty实例。现在下面的代码:

print(Base().say_hi, Base.say_hi, Derived().say_hi, Derived.say_hi)

将正确打印:

Hi Hi Hello Hello

推荐阅读