+ for (i = 0; i < len; ++i)
+ Py_XDECREF (callbacks[i]);
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+/* http://docs.python.org/release/2.5.2/ext/callingPython.html */
+static void
+py_guestfs_event_callback_wrapper (guestfs_h *g,
+ void *callback,
+ uint64_t event,
+ int event_handle,
+ int flags,
+ const char *buf, size_t buf_len,
+ const uint64_t *array, size_t array_len)
+{
+ PyGILState_STATE py_save = PyGILState_UNLOCKED;
+ PyObject *py_callback = callback;
+ PyObject *py_array;
+ PyObject *args;
+ PyObject *a;
+ size_t i;
+ PyObject *py_r;
+
+ py_array = PyList_New (array_len);
+ for (i = 0; i < array_len; ++i) {
+ a = PyLong_FromLongLong (array[i]);
+ PyList_SET_ITEM (py_array, i, a);
+ }
+
+ /* XXX As with Perl we don't pass the guestfs_h handle here. */
+ args = Py_BuildValue ("(Kis#O)",
+ (unsigned PY_LONG_LONG) event, event_handle,
+ buf, buf_len, py_array);
+
+ if (PyEval_ThreadsInitialized ())
+ py_save = PyGILState_Ensure ();
+
+ py_r = PyEval_CallObject (py_callback, args);
+
+ if (PyEval_ThreadsInitialized ())
+ PyGILState_Release (py_save);
+
+ Py_DECREF (args);
+
+ if (py_r != NULL)
+ Py_DECREF (py_r);
+ else
+ /* Callback threw an exception: print it. */
+ PyErr_PrintEx (0);
+}
+
+PyObject *
+py_guestfs_set_event_callback (PyObject *self, PyObject *args)
+{
+ PyObject *py_g;
+ guestfs_h *g;
+ PyObject *py_callback;
+ unsigned PY_LONG_LONG events;
+ int eh;
+ PyObject *py_eh;
+ char key[64];
+
+ if (!PyArg_ParseTuple (args, (char *) "OOK:guestfs_set_event_callback",
+ &py_g, &py_callback, &events))
+ return NULL;
+
+ if (!PyCallable_Check (py_callback)) {
+ PyErr_SetString (PyExc_TypeError,
+ "callback parameter is not callable "
+ "(eg. lambda or function)");
+ return NULL;
+ }
+
+ g = get_handle (py_g);
+
+ eh = guestfs_set_event_callback (g, py_guestfs_event_callback_wrapper,
+ events, 0, py_callback);
+ if (eh == -1) {
+ PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+ return NULL;
+ }
+
+ /* Increase the refcount for this callback since we are storing it
+ * in the opaque C libguestfs handle. We need to remember that we
+ * did this, so we can decrease the refcount for all undeleted
+ * callbacks left around at close time (see py_guestfs_close).
+ */
+ Py_XINCREF (py_callback);
+
+ snprintf (key, sizeof key, "_python_event_%d", eh);
+ guestfs_set_private (g, key, py_callback);
+
+ py_eh = PyInt_FromLong ((long) eh);
+ return py_eh;
+}
+
+PyObject *
+py_guestfs_delete_event_callback (PyObject *self, PyObject *args)
+{
+ PyObject *py_g;
+ guestfs_h *g;
+ int eh;
+ PyObject *py_callback;
+ char key[64];
+
+ if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_delete_event_callback",
+ &py_g, &eh))
+ return NULL;
+ g = get_handle (py_g);
+
+ snprintf (key, sizeof key, "_python_event_%d", eh);
+ py_callback = guestfs_get_private (g, key);
+ if (py_callback) {
+ Py_XDECREF (py_callback);
+ guestfs_set_private (g, key, NULL);
+ guestfs_delete_event_callback (g, eh);
+ }
+