mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
91 lines
2.8 KiB
Markdown
91 lines
2.8 KiB
Markdown
|
|
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)
|
|
|