[capi-sig] intermediate parsed representation of C/C++ API descriptions for multiple wrapper generators

Jack Jansen Jack.Jansen at cwi.nl
Sun May 2 23:47:24 CEST 2010

On  2-May-2010, at 07:27 , Stefan Behnel wrote:
>> If there is enough interest: I can start by describing bgen's
>> intermediate format, and if other people do the same for theirs we may
>> be able to get to common ground...
> Please do. I'll ask over at the Cython-users list to see if others have something to contribute to this discussion.

Ok, here goes. People interested in a (slightly) more complete writeup can read <http://homepages.cwi.nl/~jack/presentations/nluug-praatje.pdf>, but here is the basics.

The bgen intermediate format is a python file. Each C or C++ definition is transformed into a few lines of Python code that describe the definition. Here is an example (manually entered, so probably incorrect:-):

--------- test.h:
int increment(int value);
void print(const char *string);
void clear(int *location);

---------- intermediate code:
f = Function(int, 'increment', (int, 'value', InMode))

f = Function(void, 'print', (char_ptr, 'string', InMode))

f = Function(void, 'clear', (int, 'location', OutMode))
That's the basics. There is a little mangling of names going on, as you can see in the second function, so that the C type is representable as a Python identifier.

But, as you can see in the third line, there is a little more to it: patterns are applied before outputting the intermediate format. One of the patterns has turned the expected (int_ptr, 'location', InMode) argument into the (int, 'location', OutMode). The current implementation applies the patterns before creating the intermediate format, but I think that for a future implementation I would be much more in favor of having that be an extra step (so it would read intermediate code and write intermediate code).

The pattern substitution engine is really the power of bgen, because it can do much more than the simple transformation shown here. Patterns can trigger on multiple arguments, and they can also be told to look for "C-style" object-oriented code. So,

int writestream(streamptr *sp, char *buf, int nbytes);

is turned into
f = Method(int, 'writestream', (VarInputBufferSize, 'buf', InMode))

This is why I love bgen so much, because it means that the Python interface is the expected sp.writestream("hello") as opposed to the barebones writestream(sp, "hello", 5). But that's bgen-evangelism, so I'll stop here:-)

Jack Jansen, <Jack.Jansen at cwi.nl>, http://www.cwi.nl/~jack
If I can't dance I don't want to be part of your revolution -- Emma Goldman

More information about the capi-sig mailing list