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

2024-03-09

我有一个Event在 C++ 中定义的类,我使用 Boost 向 Python 公开该类。我的脚本应该从此类派生,并且每当定义新的子类时我都想进行一些初始化。

如何设置暴露的元类Event类,以便每当 Python 脚本从此类派生时,元类都可以执行所需的初始化?

我想避免在脚本中显式使用元类......

class KeyboardEvent(Event):  # This is what I want
    pass

class KeyboardEvent(Event, metaclass=EventMeta): # This is not a good solution
    pass

Edit: 部分解决方案

似乎没有办法用 Boost.Python 设置元类。下一个最好的事情是在定义类之后即兴创作并更改元类。在原生 Python 中,安全的方法 https://stackoverflow.com/a/5121381/627005更改元类的方法是:

B = MetaClass(B.__name__, B.__bases__, B.__dict__)

在 Boost 中,它看起来像这样:

BOOST_PYTHON_MODULE(event)
{
    using namespace boost::python;
    using boost::python::objects::add_to_namespace;

    class_<EventMetaClass> eventmeta("__EventMetaClass")
        ...;

    class_<Event> event("Event")
        ...;

    add_to_namespace(scope(), "Event",
        eventmeta(event["__name__"], event["__bases__"], event["__dict__"]));
}

问题是我似乎找不到用 Boost.Python 定义元类的方法,这就是我打开的原因如何使用 Boost.Python 定义 Python 元类? https://stackoverflow.com/q/9050985/627005.


如果 boost 没有提供从 C++ 内部执行此操作的方法,而且看起来也没有,那么可行的方法是创建实现元类的包装类 -

通过一点点内省,它或多或少可以自动完成。假设您的 boost 模块名为“event” - 您应该将该文件命名为 _event 或将其放入模块中,并编写一个名为“event.py”的 python 文件(或__init__.py模块上的文件或多或少会执行以下操作:

import _event

class eventmeta(type):
    ...

event_dict = globals()
for key, value in _event.__dict__.items():
    if isinstance(value, type):
        event_dict[key] = eventmeta(key, (value,),{})
    else:
        #set other module members as members of this module
        event_dict[key] = value

del key, value, event_dict

cpde 将自动将模块变量设置为等于本机“_event”模块中找到的任何名称 - 并且对于它遇到的每个类,创建一个更改元类的新类,如您的示例中所示。

这样做可能会导致元类冲突。如果是这样,方法是通过创建适当的类,使新创建的类成为本机类的代理__getattribute__ and __setattr__方法。只需在评论中询问您是否需要这样做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Boost.Python 设置包装类的元类 的相关文章

随机推荐