[C++-sig] pyplusplus: Feature requests

Matthias Baas baas at ira.uka.de
Mon Feb 27 19:26:07 CET 2006


Roman Yakovenko wrote:
> Can you create relevant test cases and send them to me? I will add the
> code that fixes it.

Here is an example class that contains three of the problems mentioned:

///////////////////////////////////////////////////////
// File: source.h

class Foo
{
   public:
   // When keywords are disabled, the arguments of this constructor
   // are not optional anymore in the Python bindings
   Foo(double x, double y=0, double z=0);

   // The copy constructor is not wrapped
   Foo(const Foo& f);

   // The index operator is not wrapped
   int operator[](int idx);
};
///////////////////////////////////////////////////////

I was still using my own version of the API using these lines:

from pyppapi import *
header("source.h")
parse()
Constructor().disableKeywordArgs()
writeFiles()

So I did nothing special except for disabling the keywords on the 
constructor. The generated code looks like this:

void register_Foo_class(){
     bp::class_< Foo >( "Foo", bp::init< double, double, double 
 >()[bp::default_call_policies()] );
}

There are three things to note:

- The optional values in the first constructor are not optional anymore 
whereas they could be made optional using init< double, optional<double, 
double> >()

- The copy constructor does not appear in the bindings

- The index operator does not appear in the bindings (Pyste also ignores 
this operator. Is there an issue with that? Couldn't this just used as 
implementation for the __getitem__ method?)


Here is another example showing the enum problem when the cache is used:

///////////////////////////////////////////////////////
class Foo
{
   public:
   enum Color { red, green, blue, black, white };
};
///////////////////////////////////////////////////////

I was using the following code to wrap the class:

from pyppapi import *
header("source.h")
cache("pypp.cache")
writeFiles()

Again, nothing special except for enabling the cache.

The generated code looks like this:

void register_Foo_class(){
     if( true ){
         typedef bp::class_< Foo > Foo_exposer_t;
         Foo_exposer_t Foo_exposer = Foo_exposer_t( "Foo" );
         bp::scope Foo_scope( Foo_exposer );
         bp::enum_<Foo::Color>("Color")
             .value("blue", Foo::blue)
             .value("green", Foo::green)
             .value("white", Foo::white)
             .value("black", Foo::black)
             .value("red", Foo::red)
             .export_values()
             ;
     }
}

When I create the bindings a second time, the order of the enum values 
is blue-black-white-green-red. These two orderings always switch back 
and forth with each invocation of pyplusplus which means the file always 
changes and gets recompiled every time.
I think it would be nice if the order could actually be that of the 
source file (which also isn't the case even when the cache is not used).


The thing about the friend functions was my fault (sort of). When I 
wanted to set up a simple example I noticed that pyplusplus actually 
supports those friend functions but the problem is that the declaration 
does not appear as children of the class declaration. That's why I was 
ignoring them (I'm ignoring everything by default and then add the 
classes I want to wrap).
I'd argue that the declarations for operators implemented as friend 
functions should also appear as children of the corresponding class 
declaration as in the Python bindings they have to be part of the class. 
Otherwise I don't see a straightforward way to address these operators 
for calling ignore()/expose() on them.

- Matthias -




More information about the Cplusplus-sig mailing list