1 /* -*- Mode: C; c-set-style: python; c-basic-offset: 4 -*-
2 * pyglib - Python bindings for GLib toolkit.
3 * Copyright (C) 1998-2003 James Henstridge
4 * 2004-2008 Johan Dahlin
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
29 #include "pyglib-private.h"
30 #include "pygmaincontext.h"
31 #include "pygoptioncontext.h"
32 #include "pygoptiongroup.h"
34 static struct _PyGLib_Functions *_PyGLib_API;
35 static int pyglib_thread_state_tls_key;
36 static PyObject *exception_table = NULL;
41 PyObject *glib, *cobject;
43 glib = PyImport_ImportModule("gi._glib");
45 if (PyErr_Occurred()) {
46 PyObject *type, *value, *traceback;
47 PyObject *py_orig_exc;
48 PyErr_Fetch(&type, &value, &traceback);
49 py_orig_exc = PyObject_Repr(value);
52 Py_XDECREF(traceback);
53 PyErr_Format(PyExc_ImportError,
54 "could not import gi._glib (error was: %s)",
55 PYGLIB_PyUnicode_AsString(py_orig_exc));
56 Py_DECREF(py_orig_exc);
58 PyErr_SetString(PyExc_ImportError,
59 "could not import gi._glib (no error given)");
64 cobject = PyObject_GetAttrString(glib, "_PyGLib_API");
65 if (cobject && PYGLIB_CPointer_Check(cobject))
66 _PyGLib_API = (struct _PyGLib_Functions *) PYGLIB_CPointer_GetPointer(cobject, "gi._glib._PyGLib_API");
68 PyErr_SetString(PyExc_ImportError,
69 "could not import gi._glib (could not find _PyGLib_API object)");
76 pyglib_init_internal(PyObject *api)
78 _PyGLib_API = (struct _PyGLib_Functions *) PYGLIB_CPointer_GetPointer(api, "gi._glib._PyGLib_API");
82 pyglib_threads_enabled(void)
84 g_return_val_if_fail (_PyGLib_API != NULL, FALSE);
86 return _PyGLib_API->threads_enabled;
90 pyglib_gil_state_ensure(void)
92 g_return_val_if_fail (_PyGLib_API != NULL, PyGILState_LOCKED);
94 if (!_PyGLib_API->threads_enabled)
95 return PyGILState_LOCKED;
97 #ifdef DISABLE_THREADING
98 return PyGILState_LOCKED;
100 return PyGILState_Ensure();
105 pyglib_gil_state_release(PyGILState_STATE state)
107 g_return_if_fail (_PyGLib_API != NULL);
109 if (!_PyGLib_API->threads_enabled)
112 #ifndef DISABLE_THREADING
113 PyGILState_Release(state);
118 * pyglib_enable_threads:
120 * Returns: TRUE if threading is enabled, FALSE otherwise.
123 #ifdef DISABLE_THREADING
125 pyglib_enable_threads(void)
127 PyErr_SetString(PyExc_RuntimeError,
128 "pyglib threading disabled at compile time");
133 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback)
135 /* Ignore, threads cannot be enabled. */
140 static GSList *thread_enabling_callbacks = NULL;
142 /* Enable threading; note that the GIL must be held by the current
143 * thread when this function is called
146 pyglib_enable_threads(void)
150 g_return_val_if_fail (_PyGLib_API != NULL, FALSE);
152 if (_PyGLib_API->threads_enabled)
155 PyEval_InitThreads();
156 if (!g_threads_got_initialized)
159 _PyGLib_API->threads_enabled = TRUE;
160 pyglib_thread_state_tls_key = PyThread_create_key();
162 for (callback = thread_enabling_callbacks; callback; callback = callback->next)
163 ((PyGLibThreadsEnabledFunc) callback->data) ();
165 g_slist_free(thread_enabling_callbacks);
170 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback)
172 if (callback && !pyglib_threads_enabled())
173 thread_enabling_callbacks = g_slist_append(thread_enabling_callbacks, callback);
178 pyglib_gil_state_ensure_py23 (void)
180 #ifdef DISABLE_THREADING
183 return PyGILState_Ensure();
188 pyglib_gil_state_release_py23 (int flag)
190 #ifndef DISABLE_THREADING
191 PyGILState_Release(flag);
196 * pyglib_block_threads:
200 pyglib_block_threads(void)
202 g_return_if_fail (_PyGLib_API != NULL);
204 if (_PyGLib_API->block_threads != NULL)
205 (* _PyGLib_API->block_threads)();
209 * pyglib_unblock_threads:
213 pyglib_unblock_threads(void)
215 g_return_if_fail (_PyGLib_API != NULL);
216 if (_PyGLib_API->unblock_threads != NULL)
217 (* _PyGLib_API->unblock_threads)();
221 * pyglib_set_thread_block_funcs:
223 * hooks to register handlers for getting GDK threads to cooperate
224 * with python threading
227 pyglib_set_thread_block_funcs (PyGLibThreadBlockFunc block_threads_func,
228 PyGLibThreadBlockFunc unblock_threads_func)
230 g_return_if_fail (_PyGLib_API != NULL);
232 _PyGLib_API->block_threads = block_threads_func;
233 _PyGLib_API->unblock_threads = unblock_threads_func;
237 * pyglib_error_marshal:
238 * @error: a pointer to the GError.
240 * Checks to see if @error has been set. If @error has been set, then a
241 * GLib.GError Python exception object is returned (but not raised).
243 * Returns: a GLib.GError Python exception object, or NULL.
246 pyglib_error_marshal (GError **error)
248 PyGILState_STATE state;
250 PyObject *exc_instance;
253 g_return_val_if_fail(error != NULL, NULL);
258 state = pyglib_gil_state_ensure();
260 exc_type = _PyGLib_API->gerror_exception;
261 if (exception_table != NULL)
264 item = PyDict_GetItem(exception_table, PYGLIB_PyLong_FromLong((*error)->domain));
269 exc_instance = PyObject_CallFunction(exc_type, "z", (*error)->message);
271 if ((*error)->domain) {
272 PyObject_SetAttrString(exc_instance, "domain",
273 d=PYGLIB_PyUnicode_FromString(g_quark_to_string((*error)->domain)));
277 PyObject_SetAttrString(exc_instance, "domain", Py_None);
279 PyObject_SetAttrString(exc_instance, "code",
280 d=PYGLIB_PyLong_FromLong((*error)->code));
283 if ((*error)->message) {
284 PyObject_SetAttrString(exc_instance, "message",
285 d=PYGLIB_PyUnicode_FromString((*error)->message));
288 PyObject_SetAttrString(exc_instance, "message", Py_None);
291 pyglib_gil_state_release(state);
297 * pyglib_error_check:
298 * @error: a pointer to the GError.
300 * Checks to see if the GError has been set. If the error has been
301 * set, then the glib.GError Python exception will be raised, and
302 * the GError cleared.
304 * Returns: True if an error was set.
307 pyglib_error_check(GError **error)
309 PyGILState_STATE state;
310 PyObject *exc_instance;
312 g_return_val_if_fail(error != NULL, FALSE);
316 state = pyglib_gil_state_ensure();
318 exc_instance = pyglib_error_marshal (error);
319 PyErr_SetObject(_PyGLib_API->gerror_exception, exc_instance);
320 Py_DECREF(exc_instance);
321 g_clear_error(error);
323 pyglib_gil_state_release(state);
329 * pyglib_gerror_exception_check:
330 * @error: a standard GLib GError ** output parameter
332 * Checks to see if a GError exception has been raised, and if so
333 * translates the python exception to a standard GLib GError. If the
334 * raised exception is not a GError then PyErr_Print() is called.
336 * Returns: 0 if no exception has been raised, -1 if it is a
337 * valid glib.GError, -2 otherwise.
340 pyglib_gerror_exception_check(GError **error)
342 PyObject *type, *value, *traceback;
343 PyObject *py_message, *py_domain, *py_code;
344 const char *bad_gerror_message;
346 PyErr_Fetch(&type, &value, &traceback);
349 PyErr_NormalizeException(&type, &value, &traceback);
351 PyErr_Restore(type, value, traceback);
356 !PyErr_GivenExceptionMatches(type,
357 (PyObject *) _PyGLib_API->gerror_exception)) {
358 PyErr_Restore(type, value, traceback);
363 Py_XDECREF(traceback);
365 py_message = PyObject_GetAttrString(value, "message");
366 if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) {
367 bad_gerror_message = "gi._glib.GError instances must have a 'message' string attribute";
368 Py_XDECREF(py_message);
372 py_domain = PyObject_GetAttrString(value, "domain");
373 if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) {
374 bad_gerror_message = "gi._glib.GError instances must have a 'domain' string attribute";
375 Py_DECREF(py_message);
376 Py_XDECREF(py_domain);
380 py_code = PyObject_GetAttrString(value, "code");
381 if (!py_code || !PYGLIB_PyLong_Check(py_code)) {
382 bad_gerror_message = "gi._glib.GError instances must have a 'code' int attribute";
383 Py_DECREF(py_message);
384 Py_DECREF(py_domain);
389 g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)),
390 PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message));
392 Py_DECREF(py_message);
394 Py_DECREF(py_domain);
399 g_set_error(error, g_quark_from_static_string("pyglib"), 0, "%s", bad_gerror_message);
400 PyErr_SetString(PyExc_ValueError, bad_gerror_message);
406 * pyglib_register_exception_for_domain:
407 * @name: name of the exception
408 * @error_domain: error domain
410 * Registers a new glib.GError exception subclass called #name for
411 * a specific #domain. This exception will be raised when a GError
412 * of the same domain is passed in to pyglib_error_check().
414 * Returns: the new exception
417 pyglib_register_exception_for_domain(gchar *name,
422 exception = PyErr_NewException(name, _PyGLib_API->gerror_exception, NULL);
424 if (exception_table == NULL)
425 exception_table = PyDict_New();
427 PyDict_SetItem(exception_table,
428 PYGLIB_PyLong_FromLong(error_domain),
435 * pyglib_main_context_new:
436 * @context: a GMainContext.
438 * Creates a wrapper for a GMainContext.
440 * Returns: the GMainContext wrapper.
443 pyglib_main_context_new(GMainContext *context)
445 return _PyGLib_API->main_context_new(context);
449 * pyg_option_group_transfer_group:
450 * @group: a GOptionGroup wrapper
452 * This is used to transfer the GOptionGroup to a GOptionContext. After this
453 * is called, the calle must handle the release of the GOptionGroup.
455 * When #NULL is returned, the GOptionGroup was already transfered.
457 * Returns: Either #NULL or the wrapped GOptionGroup.
460 pyglib_option_group_transfer_group(PyObject *obj)
462 PyGOptionGroup *self = (PyGOptionGroup*)obj;
464 if (self->is_in_context)
467 self->is_in_context = TRUE;
469 /* Here we increase the reference count of the PyGOptionGroup, because now
470 * the GOptionContext holds an reference to us (it is the userdata passed
471 * to g_option_group_new().
473 * The GOptionGroup is freed with the GOptionContext.
475 * We set it here because if we would do this in the init method we would
476 * hold two references and the PyGOptionGroup would never be freed.
484 * pyglib_option_group_new:
485 * @group: a GOptionGroup
487 * The returned GOptionGroup can't be used to set any hooks, translation domains
488 * or add entries. It's only intend is, to use for GOptionContext.add_group().
490 * Returns: the GOptionGroup wrapper.
493 pyglib_option_group_new (GOptionGroup *group)
495 return _PyGLib_API->option_group_new(group);
499 * pyglib_option_context_new:
500 * @context: a GOptionContext
502 * Returns: A new GOptionContext wrapper.
505 pyglib_option_context_new (GOptionContext *context)
507 return _PyGLib_API->option_context_new(context);
511 * pyglib_option_context_new:
512 * @context: a GTimeVal struct
514 * Converts a GTimeVal struct to a python float
516 * Returns: a float representing the timeval
519 pyglib_float_from_timeval(GTimeVal timeval)
522 ret = (double)timeval.tv_sec + (double)timeval.tv_usec * 0.000001;
523 return PyFloat_FromDouble(ret);
527 /****** Private *****/
530 * _pyglib_destroy_notify:
531 * @user_data: a PyObject pointer.
533 * A function that can be used as a GDestroyNotify callback that will
534 * call Py_DECREF on the data.
537 _pyglib_destroy_notify(gpointer user_data)
539 PyObject *obj = (PyObject *)user_data;
540 PyGILState_STATE state;
542 g_return_if_fail (_PyGLib_API != NULL);
544 state = pyglib_gil_state_ensure();
546 pyglib_gil_state_release(state);
550 _pyglib_handler_marshal(gpointer user_data)
552 PyObject *tuple, *ret;
554 PyGILState_STATE state;
556 g_return_val_if_fail(user_data != NULL, FALSE);
558 state = pyglib_gil_state_ensure();
560 tuple = (PyObject *)user_data;
561 ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0),
562 PyTuple_GetItem(tuple, 1));
567 res = PyObject_IsTrue(ret);
571 pyglib_gil_state_release(state);
577 _pyglib_generic_ptr_richcompare(void* a, void *b, int op)
584 res = (a == b) ? Py_True : Py_False;
588 res = (a != b) ? Py_True : Py_False;
592 res = (a < b) ? Py_True : Py_False;
596 res = (a <= b) ? Py_True : Py_False;
600 res = (a > b) ? Py_True : Py_False;
604 res = (a >= b) ? Py_True : Py_False;
608 res = Py_NotImplemented;
617 _pyglib_generic_long_richcompare(long a, long b, int op)
624 res = (a == b) ? Py_True : Py_False;
629 res = (a != b) ? Py_True : Py_False;
635 res = (a < b) ? Py_True : Py_False;
640 res = (a <= b) ? Py_True : Py_False;
645 res = (a > b) ? Py_True : Py_False;
650 res = (a >= b) ? Py_True : Py_False;
655 res = Py_NotImplemented;