[C++-sig] [Py++] Registration order corner case

Christopher Bruns cmbruns at stanford.edu
Thu Mar 25 21:23:34 CET 2010


Thanks Roman for your swift and thoughtful advice.  Your feedback on
this list is one of many admirable features of Py++.

I believe that the issue here goes a bit deeper than the classes' sort
order (see below)

On Thu, Mar 25, 2010 at 12:09 PM, Roman Yakovenko
<roman.yakovenko at gmail.com> wrote:
> On Thu, Mar 25, 2010 at 8:34 PM, Christopher Bruns <cmbruns at stanford.edu> wrote:
>> ...
>> //###### foo.h ###########
>> struct Foo1 { struct Foo2; };
>> struct Foo3 : public Foo1 {};
>> struct Foo1::Foo2 : public Foo3 {};
>> ...
>
> I am pretty sure Py++ doesn't export such hierarchies right. The class
> sorting algorithm is a simple DFS, which doesn't take into account
> such use case - "derived from the inner class"
>
>> The only way to avoid the registration order problem is to register
>> these classes to boost.python in exactly the order Foo1, Foo3, Foo2
>> (just like the definitions in C++).
>>
>> #include "boost/python.hpp"
>> #include "foo.h"
>> namespace bp = boost::python;
>> BOOST_PYTHON_MODULE(_foo){
>>    typedef bp::class_< Foo1 > Foo1_exposer_t;
>>    Foo1_exposer_t Foo1_exposer = Foo1_exposer_t( "Foo1" );
>>
>>    bp::class_< Foo3, bp::bases< Foo1 > >( "Foo3" );
>>
>>    bp::scope Foo1_scope( Foo1_exposer );
>>    bp::class_< Foo1::Foo2, bp::bases< Foo3 > >( "Foo2" );
>> }
>>
>> Is there a way to coax pyplusplus to produce this registration order?
>
> Yes.
> ...
> pyplusplus/creators_factory/sort_algorithms.py contains sort_classes
> function, which is a convenience wrapper around class_organizer_t
> class. You can replace this function with your own one:
>
> pypp_sort_classes = pyplusplus/creators_factory/sort_algorithms.sort_classes
>
> def my_sort_classes( classes, include_vars=False )
>    sorted = pypp_sort_classes( classes, include_vars )
>    < put class X before class Y >
>    return sorted
>
> pyplusplus/creators_factory/sort_algorithms.sort_classes = my_sort_classes

I hacked in a sort order that hard-codes the correct order of these
three classes (Foo1, Foo3, Foo2), and yet pyplusplus generates this:

#########################
BOOST_PYTHON_MODULE(_foo){
    { //::Foo1
        typedef bp::class_< Foo1 > Foo1_exposer_t;
        Foo1_exposer_t Foo1_exposer = Foo1_exposer_t( "Foo1" );
        bp::scope Foo1_scope( Foo1_exposer );
        bp::class_< Foo1::Foo2, bp::bases< Foo3 > >( "Foo2" );
    }

    bp::class_< Foo3, bp::bases< Foo1 > >( "Foo3" );
}
#########################
"RuntimeError: extension class wrapper for base class struct Foo3 has
not been created yet"

It seems that because Foo2 is an inner class of Foo1, it is always
registered in the same block as Foo1.  There is no way for Foo3 to get
registered in between.  Perhaps py++ does not yet have a way to
separate the declaration of an outer class from the declaration of its
inner classes.  Further, because I prefer to use the one-file-per
class wrapping feature of py++, there would need to be a separate file
for Foo2, which is ordinarily declared in the file Foo1.pypp.cpp, for
this case to work in  "split_module" mode.

Regards,
Christopher


More information about the Cplusplus-sig mailing list