The documentation of SWIG is pretty extensive, but there isn’t a single point that document all available macros / substitution mechanisms available while writing a typemap. It’s a nightmare to find what you’re looking for when you’re not already really familiar with it, so to save myself and maybe a few others from early hair loss, here is a quick list of some useful substitutions I found.
Assuming I’m writing an out typemap for a template<class T> class Handle;
| $1 | The local copy of the C/C++ object |
| $result | The output PyObject to return to Python |
| $1_type | The type of the C/C++ object (Handle<T>) |
| $1_descriptor | The SWIG type descriptor corresponding to Handle<T> |
| $&1_descriptor | The SWIG type descriptor corresponding to Handle<T> * |
The case I was trying to cover when I almost became bald is the following: I have a templated Handle class (as you’ve probably already guessed) that’s used to encapsulate a heap allocated data. Some API functions / methods bound in Python return such handles in place of pointers, but I wanted the those to return None in Python instead of returning an invalid handle.
So I basically needed a typemap that checked the validity of my handle, and if invalid returned None, otherwise returned the usual SWIG object. Here is the simplified typemap:
%typemap(out) Handle {
if ($1.valid() == false) {
$result = Py_None;
} else {
// this fucking $&1_descriptor is at the origin of this post...
$result = SWIG_NewPointerObj(new $type(std::move($1)), $&1_descriptor, SWIG_POINTER_OWN);
}
}