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); } }