如何使用 Boost.Python 定义 Python 元类?

Posted

技术标签:

【中文标题】如何使用 Boost.Python 定义 Python 元类?【英文标题】:How to define a Python metaclass with Boost.Python? 【发布时间】:2012-02-21 11:40:31 【问题描述】:

Python C API 有PyObject *PyType_Type 对象,相当于解释器中的type。如果我想在 C++ 中定义一个元类,我如何将type 设置为它在 Boost.Python 中的基础之一?另外,在 C++ 中定义 Python 元类时我还应该考虑哪些其他事项?

如果有 Boost.Python 解决方案,那就太理想了。如果没有,使用 Python C API(或 Boost 和 C API 的组合)的解决方案也很好。由于我的其他类都暴露在 Boost 中,所以我宁愿将 SWIG 作为最后的手段。

注意:这实际上是我试图解决的一个更大问题的一部分,如果你有兴趣,我已经在Setting metaclass of wrapped class with Boost.Python 中询问过这个问题。

【问题讨论】:

您只是在寻找 Boost.Python 解决方案吗?我想我可以用 SWIG 解决这个问题 :) @awoodland Boost.Python 更可取,但我不反对 SWIG。 好的,如果你没有得到一个好的 Boost.Python 答案,请 ping 我,用另一个 @ 提醒我,我会看看用 SWIG 做的。 我不确定这是否可能仅使用 c++ 作为 boost python 已经将公开类型的元类设置为 Boost::Python::class。您也许可以在 c++ 中编写一个具有 new 方法的类,然后将其用作 python 中的元类。 @babak 这已经足够了™,但暴露的元类仍然必须继承自 Python 的 type 的等效项。 【参考方案1】:

好吧,这感觉像是一个 hack,但它似乎有效。

#include <boost/python.hpp>

class Meta

public:
    static boost::python::object
    newClass(boost::python::object cls, std::string name, boost::python::tuple bases, boost::python::dict attrs)
    
        attrs["foo"] = "bar";
        boost::python::object types = boost::python::import("types");
        boost::python::object type = types.attr("TypeType");
        return type.attr("__new__")(type, name, bases, attrs);
    
;

BOOST_PYTHON_MODULE(meta)

    boost::python::class_<Meta>("Meta")
    .def("__new__", &Meta::newClass)
    .staticmethod("__new__");

然后在python中

from meta import Meta

class Test(object):
    __metaclass__ = Meta

print Test, Test.foo
<class '__main__.Test'> bar

我尝试了其他一些没有使用 boost::python::object 系统的东西,但无法从 python 端得到任何像这样工作的东西。

虽然严格来说这不是一个元类,因为它不继承自 type,但它的行为就像一个元类,因为 type 在调用 new 时直接在 newClass 函数中使用。如果这不是问题,那么从

更改它可能是明智的
return type.attr("__new__")(type, name, bases, attrs);

return type.attr("__new__")(cls.attr("__class__"), name, bases, attrs);

或类似的东西,所以使用 Boost::Python::class 代替 type。

【讨论】:

我试试看。它很可能不适用于 Python 3(这是我想使用的版本),但我想如果必须的话我会降级。 如果您还没有这样做,可能值得在 boost.2283326.n4.nabble.com/Python-c-sig-f2696818.html 上提问 我给你赏金是因为这个答案很好,但我还不会接受。我仍在寻找适用于 Python 3 的解决方案。如果我没有找到任何我会接受这个答案。

以上是关于如何使用 Boost.Python 定义 Python 元类?的主要内容,如果未能解决你的问题,请参考以下文章

通过 Boost Python 将 Python 函数转换为 C++,用作回调

boost python,使用除 main global 之外的命名空间

使用 Boost.Python 设置包装类的元类

boost.python 未定义符号问题

修改 Boost Python 包装类?

Boost.Python:在类外定义构造函数