1 /* libguestfs python bindings
2 * Copyright (C) 2009-2011 Red Hat Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 /* This file contains a small number of functions that are written by
20 * hand. The majority of the bindings are generated (see
30 #include "guestfs-py.h"
32 static PyObject **get_all_event_callbacks (guestfs_h *g, size_t *len_rtn);
35 py_guestfs_create (PyObject *self, PyObject *args)
39 g = guestfs_create ();
41 PyErr_SetString (PyExc_RuntimeError,
42 "guestfs.create: failed to allocate handle");
45 guestfs_set_error_handler (g, NULL, NULL);
46 /* This can return NULL, but in that case put_handle will have
47 * set the Python error string.
49 return put_handle (g);
53 py_guestfs_close (PyObject *self, PyObject *args)
55 PyThreadState *py_save = NULL;
61 if (!PyArg_ParseTuple (args, (char *) "O:guestfs_close", &py_g))
63 g = get_handle (py_g);
65 /* As in the OCaml bindings, there is a hard to solve case where the
66 * caller can delete a callback from within the callback, resulting
67 * in a double-free here. XXX
69 callbacks = get_all_event_callbacks (g, &len);
71 if (PyEval_ThreadsInitialized ())
72 py_save = PyEval_SaveThread ();
74 if (PyEval_ThreadsInitialized ())
75 PyEval_RestoreThread (py_save);
77 for (i = 0; i < len; ++i)
78 Py_XDECREF (callbacks[i]);
85 /* http://docs.python.org/release/2.5.2/ext/callingPython.html */
87 py_guestfs_event_callback_wrapper (guestfs_h *g,
92 const char *buf, size_t buf_len,
93 const uint64_t *array, size_t array_len)
95 PyGILState_STATE py_save = PyGILState_UNLOCKED;
96 PyObject *py_callback = callback;
103 py_array = PyList_New (array_len);
104 for (i = 0; i < array_len; ++i) {
105 a = PyLong_FromLongLong (array[i]);
106 PyList_SET_ITEM (py_array, i, a);
109 /* XXX As with Perl we don't pass the guestfs_h handle here. */
110 args = Py_BuildValue ("(Kis#O)",
111 (unsigned PY_LONG_LONG) event, event_handle,
112 buf, buf_len, py_array);
114 if (PyEval_ThreadsInitialized ())
115 py_save = PyGILState_Ensure ();
117 py_r = PyEval_CallObject (py_callback, args);
119 if (PyEval_ThreadsInitialized ())
120 PyGILState_Release (py_save);
127 /* Callback threw an exception: print it. */
132 py_guestfs_set_event_callback (PyObject *self, PyObject *args)
136 PyObject *py_callback;
137 unsigned PY_LONG_LONG events;
142 if (!PyArg_ParseTuple (args, (char *) "OOK:guestfs_set_event_callback",
143 &py_g, &py_callback, &events))
146 if (!PyCallable_Check (py_callback)) {
147 PyErr_SetString (PyExc_TypeError,
148 "callback parameter is not callable "
149 "(eg. lambda or function)");
153 g = get_handle (py_g);
155 eh = guestfs_set_event_callback (g, py_guestfs_event_callback_wrapper,
156 events, 0, py_callback);
158 PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
162 /* Increase the refcount for this callback since we are storing it
163 * in the opaque C libguestfs handle. We need to remember that we
164 * did this, so we can decrease the refcount for all undeleted
165 * callbacks left around at close time (see py_guestfs_close).
167 Py_XINCREF (py_callback);
169 snprintf (key, sizeof key, "_python_event_%d", eh);
170 guestfs_set_private (g, key, py_callback);
172 py_eh = PyLong_FromLong ((long) eh);
177 py_guestfs_delete_event_callback (PyObject *self, PyObject *args)
182 PyObject *py_callback;
185 if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_delete_event_callback",
188 g = get_handle (py_g);
190 snprintf (key, sizeof key, "_python_event_%d", eh);
191 py_callback = guestfs_get_private (g, key);
193 Py_XDECREF (py_callback);
194 guestfs_set_private (g, key, NULL);
195 guestfs_delete_event_callback (g, eh);
203 get_all_event_callbacks (guestfs_h *g, size_t *len_rtn)
210 /* Count the length of the array that will be needed. */
212 cb = guestfs_first_private (g, &key);
214 if (strncmp (key, "_python_event_", strlen ("_python_event_")) == 0)
216 cb = guestfs_next_private (g, &key);
219 /* Copy them into the return array. */
220 r = guestfs_safe_malloc (g, sizeof (PyObject *) * (*len_rtn));
223 cb = guestfs_first_private (g, &key);
225 if (strncmp (key, "_python_event_", strlen ("_python_event_")) == 0) {
229 cb = guestfs_next_private (g, &key);