SIP Python bindings generator - nested templates

Jim jbublitzNO at SPAMnwinternet.com
Thu Jan 16 21:49:54 CET 2003


Pakewak wrote:
> The SIP generator doesn't seem to allow nested template types. I have a 
> method called:

sip itself doesn't allow template types at all. You
have to hand write a %MappedType section in the .sip
file (or a separate file that you include).

> virtual plSMat<plSquareMatrix<double>,3> GetOrientationMatrix() const;

> Now I manually added the code for this function in the generated code, which 
> works, but this is not very convenient. Is there a work-around for SIP for 
> this problem?

Add a %MappedType section that specifies the
C/C++ code for converting to/from Python. There
are examples in PyQt or PyKDE, or see below.
(The examples are actually much simpler than
the explanation). The %MappedType code will
probably be identical to what you've already
written and inserted manually.

> I also searched for a directive (like %HeaderCode) that just copies the 
> enclosed code into the generated code without processing. There doesn't 
> seem to be one. Something like "%HeaderCode", but one which doesn't replace 
> the code at the top.

%C++Code -- for example (in some .sip file):

%C++Code
int someFunction (char * aString)
{
     return strlen (aString);
}
%End

int someFunction (char *); // generate the binding code
                            // for the C++ code.

I don't think that's what you want for your template
problem though. For this to work, you'd need to
hook it into the rest of the sip runtime framework,
and sip already knows how to do that. Here's the basic
scheme:

// in your sip files, you can either assign
// a new name to the template type, or just
// use it as the identifier - sip will accept
// the <'s and >'s as part of the identifier
%MappedType plSMat<plSquareMatrix<double>, 3>
{
%HeaderCode
#include <<the header for the template class>>
#include <<any other headers you need>>
// you can stick a typedef here if you want
// to create a new name for the template type
%End

%ConvertFromTypeCode

// sipCpp will contain a pointer to the template
// object. You want to take sipCpp and convert
// it into some PyObject(s) and return those
// at the end of this section. Since this is
// in C/C++, you have to use Py_BuildValue if
// you need to return more than a single Python
// object (returns a tuple - a list of Python
// objects is a single object though). sipCpp
// can be null too, so test for that.

%End

%ConvertToTypeCode

// sipPy will contain a pointer to the PyObject.
// Convert that to the corresponding C/C++
// object and set sipCppPtr to point to that.
// Return 1 on success or 0 on failure

%End
};

Think of sipCpp as a global void * and cast
it to the proper type in your code (but don't
declare it). sipPy is a PyObject *.

In the case of a nested template type, you'll
need to convert the inner type(s) to simpler
objects that the outermost type can contain/represent
in Python - either basic types or objects Python
knows about (from other bindings, for example).

Mapped types can't be instantiated as such - they're
replaced in your program by the corresponding (mapped
to) Python type. For example:

in some .sip file:

QList<int> someMethod (QList<int>);

%MappedType QList<int>
{
     ...

%ConvertFromTypeCode

     PyObject *list = PyList_New (0);

     if (sipCpp)
     {
         QList<int> *cppList = (QList<int> *)sipCpp;

         // convert here
     }

     return list; // empty if sipCpp == 0
%End

     ...

}

in Python:

list = [1, 2, 3]
newList = someMethod (list)

'someMethod' (in Python) would take and return a
Python list of int. QList<int>* and QList<int>&
will also be handled by sip correctly and
automatically - you write the code for QList<int>
in either case.

There will be sip docs and a tutorial coming in
the future -- hopefully some time this year. For
now, your best bet is the PyKDE mailing list:

http://mats.gmd.de/mailman/listinfo/pykde

or the PyQt and PyKDE source code.


Jim





More information about the Python-list mailing list