]> granicus.if.org Git - libnl/commitdiff
python: allow callback function to be a class method
authorArend van Spriel <arend@broadcom.com>
Thu, 5 Sep 2013 12:11:27 +0000 (14:11 +0200)
committerThomas Graf <tgraf@suug.ch>
Thu, 5 Sep 2013 15:46:00 +0000 (17:46 +0200)
The callback functionality only worked for regular Python
functions. With this patch it also allows the callback
to be a class method (bounded or unbounded) as show in
example below.

class test_class(object):
def my_callback(self, msg, arg):
print('handling %s' % str(msg))

s = netlink.core.Socket()
testobj = test_class()
netlink.capi.py_nl_cb_set(cb, netlink.capi.NL_CB_VALID,
  netlink.capi.NL_CB_CUSTOM,
  test_class.my_callback, testobj)
netlink.capi.py_nl_cb_err(cb, netlink.capi.NL_CB_CUSTOM,
                          test_class.my_callback, s)

Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
python/netlink/capi.i

index 785e0a6828ee5023ec9d29486dc182ea1932f510..507c220ac8f6a2a01b1a8b3712bef23fbc91da40 100644 (file)
@@ -9,6 +9,7 @@
 #include <netlink/attr.h>
 #include <net/if.h>
 
+#define DEBUG
 #include "utils.h"
 %}
 
@@ -613,14 +614,27 @@ static int nl_recv_msg_handler(struct nl_msg *msg, void *arg)
        PyObject *msgobj;
        PyObject *cbparobj;
        PyObject *resobj;
+       PyObject *funcobj;
        int result;
 
        if (!cbd)
                return NL_STOP;
        msgobj = SWIG_NewPointerObj(SWIG_as_voidptr(msg),
                                    SWIGTYPE_p_nl_msg, 0 |  0 );
-       cbparobj = Py_BuildValue("(OO)", msgobj, cbd->cba);
-       resobj = PyObject_CallObject(cbd->cbf, cbparobj);
+       /* add selfobj if callback is a method */
+       if (cbd->cbf && PyMethod_Check(cbd->cbf)) {
+               PyObject *selfobj = PyMethod_Self(cbd->cbf);
+               cbparobj = Py_BuildValue("(OOO)", selfobj ? selfobj : cbd->cba,
+                                        msgobj, cbd->cba);
+               funcobj = PyMethod_Function(cbd->cbf);
+               pynl_dbg("callback %sbounded instance method %p\n",
+                        selfobj ? "" : "un", funcobj);
+       } else {
+               cbparobj = Py_BuildValue("(OO)", msgobj, cbd->cba);
+               funcobj = cbd->cbf;
+               pynl_dbg("callback function %p\n", funcobj);
+       }
+       resobj = PyObject_CallObject(funcobj, cbparobj);
        Py_DECREF(cbparobj);
        if (resobj == NULL)
                return NL_STOP;
@@ -637,14 +651,24 @@ static int nl_recv_err_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
        PyObject *errobj;
        PyObject *cbparobj;
        PyObject *resobj;
+       PyObject *funcobj;
        int result;
 
        if (!cbd)
                return NL_STOP;
        errobj = SWIG_NewPointerObj(SWIG_as_voidptr(err),
                                    SWIGTYPE_p_nlmsgerr, 0 |  0 );
-       cbparobj = Py_BuildValue("(OO)", errobj, cbd->cba);
-       resobj = PyObject_CallObject(cbd->cbf, cbparobj);
+       /* add selfobj if callback is a method */
+       if (cbd->cbf && PyMethod_Check(cbd->cbf)) {
+               PyObject *selfobj = PyMethod_Self(cbd->cbf);
+               cbparobj = Py_BuildValue("(OOO)", selfobj ? selfobj : cbd->cba,
+                                        errobj, cbd->cba);
+               funcobj = PyMethod_Function(cbd->cbf);
+       } else {
+               cbparobj = Py_BuildValue("(OO)", errobj, cbd->cba);
+               funcobj = cbd->cbf;
+       }
+       resobj = PyObject_CallObject(funcobj, cbparobj);
        Py_DECREF(cbparobj);
        if (resobj == NULL)
                return NL_STOP;