使用 Boost.Python 设置包装类的元类
我有一个用 C++ 定义的 Event
类,我使用 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
编辑: 解决方案的一部分
似乎无法使用 Boost.Python 设置元类。下一个最好的事情是在定义类之后即兴创作并更改元类。在原生 Python 中,更改元类的安全方法是这样做:
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 元类?。
I have an Event
class defined in C++ that I expose to Python using Boost. My scripts are expected to derive from this class, and I'd like to do some initialization whenever a new child class is defined.
How can I set the metaclass of the exposed Event
class such that whenever a Python script derives from this class, the metaclass could do the required initialization?
I would like to avoid having to explicitly use a metaclass in the scripts...
class KeyboardEvent(Event): # This is what I want
pass
class KeyboardEvent(Event, metaclass=EventMeta): # This is not a good solution
pass
Edit: Part of the solution
It seems there's no way to set the metaclass with Boost.Python. The next best thing is to improvise and change the metaclass after the class was defined. In native Python, the safe way to change a metaclass is to do this:
B = MetaClass(B.__name__, B.__bases__, B.__dict__)
In Boost, it'd look something like this:
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__"]));
}
The problem is that I can't seem to find a way to define a metaclass with Boost.Python, which is why I've opened How to define a Python metaclass with Boost.Python?.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果 boost 没有提供从 c++ 中做到这一点的方法,而且看起来也没有,那么可行的方法是创建实现元类的包装类 -
它可以或多或少地自动完成,使用一点点内省。假设您的 boost 模块名为“event” - 您应该将该文件命名为 _event 或将其放入模块中,并编写一个名为“event.py”的 python 文件(或
__init__.py 模块上的文件或多或少会执行此操作:
Thos cpde 将自动将模块变量设置为等于本机“_event”模块中找到的任何名称 - 并且对于它遇到的每个类,创建一个更改元类的新类,如你的例子
可能 。如果这样做会导致元类冲突,则方法是通过创建适当的 __getattribute__ 和 __setattr__ 来使新创建的类成为本机类的代理。 > 方法,只需在评论中询问您是否需要这样做。
If boost does not offer a way to do it from withn c++, and it looks like it don't, the way to go is to create wrapper classes that implement the metaclass -
It can be done more or less automatically usign a ittle bit of instrospection. Let's suppose your boost module is named "event" - you should either name the file as _event or place it inside you module, and write an python file - named "event.py" (or an
__init__.py
file on your module that would do more or less this:Thos cpde will automatically set module variables equal to any names found in the native"_event" module - and for each class it encounters, create a new class changing the metaclass, as in your example.
It may be that you get a metaclass conflict by doing this. If so, the way is to make the newly created classes to be proxies to the native classes, by creating proper
__getattribute__
and__setattr__
methods. Just ask in a comment if you will need to do that.