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.
--
http://mail.python.org/mailman/listinfo/python-list