2.8 KiB
This is an FAQ-style repository of SWiG incantations that are regularly needed.
Remove an argument from a prototype (because it doesn't make sense in the context of IDAPython)
%typemap(in,numinputs=0) int length
{
$1 = -1; // always -1 in IDAPython
}
Add a parameter to a C++ notification
Assume a notification named struc_renamed, to which you just
added a bool success parameter (to carry along information about the
operation's success so far):
struc_renamed, ///< A structure type has been renamed.
///< \param sptr (::struc_t *)
///< \param success (bool) // <--------- new
That new parameter will be picked up by the hooks-producing code automatically (great!), which means existing hooks are now broken (bad.)
We need to add support for calling into "old-style" hooks. That's done
through the patch_codegen.py mechanism, and in particular the
director_method_call_arity_cap rule. Something like this should do:
"SwigDirector_IDB_Hooks::struc_renamed" : [
("director_method_call_arity_cap", (
False, # add GIL lock
"struc_renamed",
"(method ,(PyObject *)obj0,(__argcnt < 3 ? nullptr : (PyObject *)obj1), nullptr)",
"(swig_get_self(), (PyObject *) swig_method_name ,(PyObject *)obj0,(__argcnt < 3 ? nullptr : (PyObject *)obj1), nullptr)")
)),
],
Handle a virtual method's "output" parameter in a director
Assume you have a virtual method taking an 'output' argument:
void merge_node_helper_t::get_column_headers(qstrvec_t *out, ...)
The neat thing to do here is to let Python implementations do the following:
def get_column_headers(self, ...):
# ...
return ["Name", "Address"]
To achieve that, you want to use the directorargout typemap:
%typemap(directorargout) qstrvec_t * (qstrvec_t tmp)
{ // %typemap(directorargout) qstrvec_t *
if ( PyW_PySeqToStrVec(&tmp, $result) >= 0 )
{
$1->swap(tmp);
}
else
{
Swig::DirectorTypeMismatchException::raise(
SWIG_ErrorType(SWIG_TypeError),
"in output value of type 'qstrvec_t' in method '$symname'");
}
}
"intercept" access to a structure/class field, in order to perform extra work
For example, idainfo.lflags bits should be set using proper setters,
because they can have side-effects.
. tell swig to consider the member as unreachable:
%ignore idainfo::lflags;
. extend the type to "manually" provide the field:
%extend idainfo
{
// ...
uint32 _get_lflags() const { return $self->lflags; }
void _set_lflags(uint32 _f)
{
// do the job here
}
%pythoncode {
lflags = property(_get_lflags, _set_lflags)