How to define a Python metaclass with Boost.Python?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How to define a Python metaclass with Boost.Python?

paulcmnt
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. (The version I'm using is Python 3.)
Reply | Threaded
Open this post in threaded view
|

Re: How to define a Python metaclass with Boost.Python?

Jim Bosch-2
On 02/07/2012 01:35 AM, paulcmnt wrote:
> 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. (The version I'm using is Python 3.)
>

I'm afraid this isn't really supported.  All Boost.Python classes have
to use a specific Boost.Python metaclass that's defined deep in the
bowels of some Boost.Python source file, and there's really no way to
override that at present.

This might be a nice feature for the future, but I haven't thought too
deeply about how to make it work or why one would want to do it.  If you
have a specific use case for a custom metaclass, I'd love to hear what
it is.

Jim
_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|

Re: How to define a Python metaclass with Boost.Python?

paulcmnt
In reply to this post by paulcmnt

---------- Forwarded message ----------
From: Jim Bosch <[hidden email]>
To: Development of Python/C++ integration <[hidden email]>
Cc: 
Date: Tue, 07 Feb 2012 11:14:54 -0500
Subject: Re: [C++-sig] How to define a Python metaclass with Boost.Python?
On 02/07/2012 01:35 AM, paulcmnt wrote:
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. (The version I'm using is Python 3.)


I'm afraid this isn't really supported.  All Boost.Python classes have to use a specific Boost.Python metaclass that's defined deep in the bowels of some Boost.Python source file, and there's really no way to override that at present.

This might be a nice feature for the future, but I haven't thought too deeply about how to make it work or why one would want to do it.  If you have a specific use case for a custom metaclass, I'd love to hear what it is.

Jim


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 the EventDispatcher (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__))


_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|

Re: How to define a Python metaclass with Boost.Python?

Jim Bosch-2
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
_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|

Re: How to define a Python metaclass with Boost.Python?

paulcmnt
In reply to this post by paulcmnt

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


I don't think it's impossible to set a metaclass of another class with Boost.Python. The trick is actually pretty similar to the one above.

>>> class Foo:
...    pass
...
>>> Foo = FooMeta(Foo.__name__, Foo.__bases__, dict(Foo.__dict__)) 

You first define the class in Boost.Python as you normally would, then do the equivalent of the code above. This should work, unless, of course, there's some subtle detail I'm not aware of.

_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|

Re: How to define a Python metaclass with Boost.Python?

Jim Bosch-2
On 02/11/2012 04:15 PM, Paul-Cristian Manta wrote:

>
> I don't think it's impossible to set a metaclass of another class with
> Boost.Python. The trick is actually pretty similar to the one above.
>
>  >>> class Foo:
> ...    pass
> ...
>  >>> Foo = FooMeta(Foo.__name__, Foo.__bases__, dict(Foo.__dict__))
>
> You first define the class in Boost.Python as you normally would, then
> do the equivalent of the code above. This should work, unless, of
> course, there's some subtle detail I'm not aware of.
>

Ah, yes.  I see what you're talking about now.  You'll probably need to
have FooMeta inherit from the Boost.Python metaclass and delegate to its
__call__ to make sure the Boost.Python metaclass gets to do its magic
too.  But I think that ought to be enough to make it work.

Good thinking - glad you didn't get discouraged by my pessimism!

Jim

_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig