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

发布于 2024-12-29 11:03:34 字数 559 浏览 3 评论 0原文

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

如果有一个 Boost.Python 解决方案那就太好了。如果没有,使用 Python C API(或 Boost 和 C API 的组合)的解决方案也不错。由于我的其他类都使用 Boost,我宁愿将 SWIG 作为最后的手段。

注意:这实际上是我试图解决的一个更大问题的一部分,我在如果您有兴趣,请使用 Boost.Python 设置包装类的元类

The Python C API has the PyObject *PyType_Type object, which is equivalent to type in the interpreter. If I want to define a metaclass in C++, how can I set type as one of its bases in Boost.Python? Also, what other things should I take into consideration when defining a Python metaclass in C++?

It'd be ideal if there was a Boost.Python solution to this. If not, a solution that uses the Python C API (or a combination of Boost and the C API) is good as well. Since my other classes are exposed with Boost, I'd rather leave SWIG as a last resort.

Note: This is actually part of a bigger problem I'm trying to solve, which I've asked about in Setting metaclass of wrapped class with Boost.Python, if you're interested.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绾颜 2025-01-05 11:03:34

好吧,这感觉像是黑客,但似乎有效。

#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 继承的,但它的行为就像元类,因为在调用 new 时,在 newClass 函数中直接使用 type。如果这不是问题,那么明智的做法是将其从 更改为

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

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

类似的内容,因此使用 Boost::Python::class 而不是类型。

Okay this feels like a hack but it seems to work.

#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__");
}

then in python

from meta import Meta

class Test(object):
    __metaclass__ = Meta

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

I tried some other things which didn't use the boost::python::object system but couldn't get anything that worked like this from the python side.

Although strictly speaking this isnt a metaclass as it doesnt inherit from type, but it behaves like one because type is used directly in the newClass function when calling new. If thats not a problem then it might be wise to change it from

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

to

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

or something similar so Boost::Python::class is used instead of type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文