使用Boost.Python设置包装类的元类 [英] Setting metaclass of wrapped class with Boost.Python

查看:206
本文介绍了使用Boost.Python设置包装类的元类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在C ++中定义的事件类,我使用Boost暴露给Python。我的脚本应该从这个类派生,我想做一些初始化每当一个新的子类定义。



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



我想避免在脚本中明确使用元类...

  class KeyboardEvent(Event):#This is我想要的
pass

class KeyboardEvent(Event,metaclass = EventMeta):#这不是一个好的解决方案
pass






编辑: 解决方案的一部分 p>

似乎没有办法用Boost.Python设置元类。下一个最好的事情是在类被定义之后即兴和改变元类。在本机Python中,更改元类的安全方式是这样做的:

  B = MetaClass(B .__ name__,B .__ bases__,B .__ dict__)

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

  BOOST_PYTHON_MODULE $ b {
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__])));
}

问题是我似乎找不到一种方法来定义metaclass with Boost.Python,这就是为什么我已经打开如何使用Boost.Python定义Python元类?。 / p>

解决方案

如果boost没有提供一个方法来从with c ++,它看起来像没有, go是创建实现元类的包装类 -



它可以做或多或少自动使用一个itbit位的内省。让我们假设你的boost模块被命名为event - 你应该将文件命名为_event或者将它放在你的模块中,并写一个名为event.py的python文件(或 __ init__.py 您的模块上的文件,可以做更多或更少的这:

  import _event 

class eventmeta(type):
...

event_dict = globals()
for键,值在_event .__ dict __。items():
如果isinstance(value,type):
event_dict [key] = eventmeta(key,(value,),{})
else:
#set其他模块成员作为此模块的成员
event_dict [key] = value

del key,value,event_dict

Thos cpde会自动将模块变量设置为等于本地_event模块中找到的任何名称,对于遇到的每个类,请创建一个更改元类的新类,如示例中所示。



这可能是你通过这样做得到一个元类冲突。如果是这样,方法是通过创建适当的 __ getattribute__,使新创建的类成为本地类的代理 __ setattr __ 方法。请在评论中提出,如果您需要这样做。


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?.

解决方案

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:

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

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.

这篇关于使用Boost.Python设置包装类的元类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆