[C++-sig] How to define a Python metaclass with Boost.Python?

Jim Bosch talljimbo at gmail.com
Sat Feb 11 06:09:24 CET 2012


Sorry about the long delay...

On 02/08/2012 09:24 AM, Paul-Cristian Manta wrote:

> In my application I have a base Event class and both C++ and Python
> inherit from this base and define new types of events. Clients can
> subscribe a certain function to a certain type of event.
>
>  >>> events = EventDispatcher()
>  >>> sub = events.subscribe(KeyboardEvent, on_keyboard_event)
>  >>> sub.cancel()
>
> When an event is posted to theEventDispatcher (from either C++ or
> Python), all functions that are subscribed to that event, /or to a base
> of that event/, are called.
>
> Because of how the system is supposed to work, I need a common way to
> determine type and parents of an event at runtime, regardless of whether
> the event class was defined in C++ or Python; I do this with a custom
> EventTypeInfo class.
>
> The metaclass that I would like to define in C++ would add a
> __cpp_event_typeinfo attribute to each event class defined in Python,
> which I can then grab when I need it.
>
> *A possible solution.* I though a good enough way of defining a
> metaclass in Boost.Python would be to the equivalent of this code below.
> Do you think there are any safety problem with doing something like
> this, some compatibly problem that could arise with the other
> Boost.Python classes?
>
>  >>> class Meta:
> ...    pass
> ...
>  >>> Meta = type(Meta.__name__, (type,), dict(Meta.__dict__))
>

This is indeed a perfectly valid way to make a metaclass, and it should 
definitely work to do the same thing in C++ using the C API and/or 
Boost.Python.

The trouble is using that metaclass as the type of a 
Boost.Python-wrapped C++ class...that's what I think is basically 
impossible.

Of course, if you just want to inject some attributes into a wrapped 
class, you can do that in Boost.Python without a metaclass.  You'd write 
a function that takes a boost::python::object and adds the attributes 
you want to it.  Calling that function with a boost::python::class_ 
object would then add the attribute, just like a metaclass would.


Jim


More information about the Cplusplus-sig mailing list