new extension generator for C++

Rouslan Korneychuk rouslank at msn.com
Mon May 3 16:44:02 EDT 2010


Hi, I'm new here. I'm working on a program that exposes C++ declarations 
to Python and I was wondering if there is any interest in it.

It's a hobby project. I was originally using Boost.Python on another 
project but found a couple of things I didn't like. Eg: you can't really 
have private constructors. If you want a Python object created, you 
either have to expose the constructor in Python, or create an instance 
of the object somewhere else in memory, and have it either copied to the 
PyObject or have the PyObject hold a reference to it. I was working on a 
rudimentary 3D game engine that was a Python extension. It was important 
to avoid copying potentially huge amounts of data, but to have almost 
every PyObject just be a pointer to another object (and the object 
already is just a few or even one pointer) seemed like an pointless 
compromise, considering that I was writing code that was specifically 
designed to be a Python extension (There was also another issue I came 
across but don't remember now).

So I looked for other solutions and noticed that Py++ (which simply 
generates Boost.Python code for you) was based on a seperate program 
called GCCXML. I figured I could use GCCXML and generate code however I 
wanted. So I did.

My program generates human-readable code (it even uses proper 
indentation). The program still has a lot of work to be done on it, but 
it can already generate working Python extensions.

It takes an input file like this:
<?xml version="1.0"?>
<module name="testmodule" include="main.h">
     <doc>module doc string</doc>

     <class name="AClass" type="MyClass">
         <doc>class doc string</doc>
         <init/>
         <member cmember="value"/>
         <def func="greet"/>
         <propery get="getX" set="setX"/>
     </class>
</module>

You can probably figure out what the resulting code does. The goal is to 
generate code that is as close to hand-written code as possible. It even 
forgoes using PyArg_ParseTupleAndKeywords and has the argument checks 
hard-wired. It also generates a header file that contains a PyObject 
implementation of MyClass called obj_AClass, with every constructor 
fowarded and with the new and delete operators overloaded to play nice 
with Python's memory handler:
...
extern PyTypeObject obj_AClassType;

struct obj_AClass {
     PyObject_HEAD
     MyClass base;
     bool initialized;

     void *operator new(size_t s) {
         void *ptr = PyMem_Malloc(s);
         if(!ptr) throw std::bad_alloc();
         return ptr;
     }

     void operator delete(void *ptr) {
         PyMem_Free(ptr);
     }

     obj_AClass(MyClass const & _0) : base(_0) {
         PyObject_Init(reinterpret_cast<PyObject*>(this),&obj_AClassType);
         initialized = true;
     }

     obj_AClass(unsigned int _0) : base(_0) {
         PyObject_Init(reinterpret_cast<PyObject*>(this),&obj_AClassType);
         initialized = true;
     }

};
...

If you want to expose one overload of a constructor or function but not 
the others, you can add overload="list,of,args" to <init/> or <def/>. 
Default values for arguments are handled automatically. When handling 
overloaded functions, it checks the types of the arguments to pick the 
best overload, taking into consideration polymorphism and the fact that 
basic types like ints can be converted from one-another. It will 
automatically detect if two overloads match to the same set of Python 
arguments (eg: void func(float) vs void func(double)). The only issue is 
it will not use keyword arguments for overloaded functions (I don't know 
if that can even be done reliably *and* efficiently. I would need to 
give it more thought).

If there is enough interest I can put this project up on SourceForge or 
Google Code.



More information about the Python-list mailing list