From 3656585dd88487de9a1f2a839b37a69bf3520ae3 Mon Sep 17 00:00:00 2001 From: "gergely.erdelyi" Date: Sun, 17 Aug 2008 17:45:06 +0000 Subject: [PATCH] Implemented add_menu_item() and the required callbacks. Big thanks to Ross Kinder for the patch. --- swig/kernwin.i | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ swig/typeconv.i | 8 +++++++ 2 files changed, 67 insertions(+) diff --git a/swig/kernwin.i b/swig/kernwin.i index 5b59e50..61157bd 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -69,6 +69,65 @@ def askseg(defval, format): %ignore skipSpaces; %ignore stristr; +%{ +bool idaapi py_menu_item_callback(void *userdata) +{ + PyObject *func, *args, *result; + bool ret = 0; + + // userdata is a tuple of ( func, args ) + // func and args are borrowed references from userdata + func = PyTuple_GET_ITEM(userdata, 0); + args = PyTuple_GET_ITEM(userdata, 1); + + // call the python function + result = PyEval_CallObject(func, args); + + // we cannot raise an exception in the callback, just print it. + if (!result) { + PyErr_Print(); + return 0; + } + + // if the function returned a non-false value, then return 1 to ida, + // overwise return 0 + if (PyObject_IsTrue(result)) { + ret = 1; + } + Py_DECREF(result); + + return ret; +} +%} + +%rename (add_menu_item) wrap_add_menu_item; +%inline %{ +bool wrap_add_menu_item ( + const char *menupath, + const char *name, + const char *hotkey, + int flags, + PyObject *pyfunc, + PyObject *args) { + // FIXME: probably should keep track of this data, and destroy it when the menu item is removed + PyObject *cb_data; + + if (args == Py_None) { + Py_DECREF(Py_None); + args = PyTuple_New( 0 ); + if (!args) + return 0; + } + + if(!PyTuple_Check(args)) { + PyErr_SetString(PyExc_TypeError, "args must be a tuple or None"); + return 0; + } + + cb_data = Py_BuildValue("(OO)", pyfunc, args); + return add_menu_item(menupath, name, hotkey, flags, py_menu_item_callback, (void *)cb_data); +} +%} %include "kernwin.hpp" diff --git a/swig/typeconv.i b/swig/typeconv.i index 1c7a216..f054895 100644 --- a/swig/typeconv.i +++ b/swig/typeconv.i @@ -80,3 +80,11 @@ } %enddef +// Check that the argument is a callable Python object +%typemap(in) PyObject *pyfunc { + if (!PyCallable_Check($input)) { + PyErr_SetString(PyExc_TypeError, "Expecting a callable object"); + return NULL; + } + $1 = $input; +}