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
;
38 static PyTypeObject
*_PyGMainContext_Type
;
39 #define PyGMainContext_Type (*_PyGMainContext_Type)
41 static PyTypeObject
*_PyGOptionGroup_Type
;
42 #define PyGOptionGroup_Type (*_PyGOptionGroup_Type)
44 static PyTypeObject
*_PyGOptionContext_Type
;
45 #define PyGOptionContext_Type (*_PyGOptionContext_Type)
50 PyObject
*glib
, *cobject
;
52 glib
= PyImport_ImportModule("glib");
54 if (PyErr_Occurred()) {
55 PyObject
*type
, *value
, *traceback
;
56 PyObject
*py_orig_exc
;
57 PyErr_Fetch(&type
, &value
, &traceback
);
58 py_orig_exc
= PyObject_Repr(value
);
61 Py_XDECREF(traceback
);
62 PyErr_Format(PyExc_ImportError
,
63 "could not import glib (error was: %s)",
64 _PyUnicode_AsString(py_orig_exc
));
65 Py_DECREF(py_orig_exc
);
67 PyErr_SetString(PyExc_ImportError
,
68 "could not import glib (no error given)");
73 cobject
= PyObject_GetAttrString(glib
, "_PyGLib_API");
74 if (cobject
&& PyCObject_Check(cobject
))
75 _PyGLib_API
= (struct _PyGLib_Functions
*) PyCObject_AsVoidPtr(cobject
);
77 PyErr_SetString(PyExc_ImportError
,
78 "could not import glib (could not find _PyGLib_API object)");
83 _PyGMainContext_Type
= (PyTypeObject
*)PyObject_GetAttrString(glib
, "MainContext");
84 _PyGOptionGroup_Type
= (PyTypeObject
*)PyObject_GetAttrString(glib
, "OptionGroup");
85 _PyGOptionContext_Type
= (PyTypeObject
*)PyObject_GetAttrString(glib
, "OptionContext");
89 pyglib_init_internal(PyObject
*api
)
91 _PyGLib_API
= (struct _PyGLib_Functions
*) PyCObject_AsVoidPtr(api
);
95 pyglib_threads_enabled(void)
97 g_return_val_if_fail (_PyGLib_API
!= NULL
, FALSE
);
99 return _PyGLib_API
->threads_enabled
;
103 pyglib_gil_state_ensure(void)
105 g_return_val_if_fail (_PyGLib_API
!= NULL
, PyGILState_LOCKED
);
107 if (!_PyGLib_API
->threads_enabled
)
108 return PyGILState_LOCKED
;
110 return PyGILState_Ensure();
114 pyglib_gil_state_release(PyGILState_STATE state
)
116 g_return_if_fail (_PyGLib_API
!= NULL
);
118 if (!_PyGLib_API
->threads_enabled
)
121 PyGILState_Release(state
);
125 * pyglib_enable_threads:
127 * Returns: TRUE if threading is enabled, FALSE otherwise.
130 #ifdef DISABLE_THREADING
132 pyglib_enable_threads(void)
134 PyErr_SetString(PyExc_RuntimeError
,
135 "pyglib threading disabled at compile time");
140 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback
)
142 /* Ignore, threads cannot be enabled. */
147 static GSList
*thread_enabling_callbacks
= NULL
;
149 /* Enable threading; note that the GIL must be held by the current
150 * thread when this function is called
153 pyglib_enable_threads(void)
157 g_return_val_if_fail (_PyGLib_API
!= NULL
, FALSE
);
159 if (_PyGLib_API
->threads_enabled
)
162 PyEval_InitThreads();
163 if (!g_threads_got_initialized
)
166 _PyGLib_API
->threads_enabled
= TRUE
;
167 pyglib_thread_state_tls_key
= PyThread_create_key();
169 for (callback
= thread_enabling_callbacks
; callback
; callback
= callback
->next
)
170 ((PyGLibThreadsEnabledFunc
) callback
->data
) ();
172 g_slist_free(thread_enabling_callbacks
);
177 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback
)
179 if (callback
&& !pyglib_threads_enabled())
180 thread_enabling_callbacks
= g_slist_append(thread_enabling_callbacks
, callback
);
185 pyglib_gil_state_ensure_py23 (void)
187 return PyGILState_Ensure();
191 pyglib_gil_state_release_py23 (int flag
)
193 PyGILState_Release(flag
);
197 * pyglib_block_threads:
201 pyglib_block_threads(void)
203 g_return_if_fail (_PyGLib_API
!= NULL
);
205 if (_PyGLib_API
->block_threads
!= NULL
)
206 (* _PyGLib_API
->block_threads
)();
210 * pyglib_unblock_threads:
214 pyglib_unblock_threads(void)
216 g_return_if_fail (_PyGLib_API
!= NULL
);
217 if (_PyGLib_API
->unblock_threads
!= NULL
)
218 (* _PyGLib_API
->unblock_threads
)();
222 * pyglib_set_thread_block_funcs:
224 * hooks to register handlers for getting GDK threads to cooperate
225 * with python threading
228 pyglib_set_thread_block_funcs (PyGLibThreadBlockFunc block_threads_func
,
229 PyGLibThreadBlockFunc unblock_threads_func
)
231 g_return_if_fail (_PyGLib_API
!= NULL
);
233 _PyGLib_API
->block_threads
= block_threads_func
;
234 _PyGLib_API
->unblock_threads
= unblock_threads_func
;
239 * pyglib_error_check:
240 * @error: a pointer to the GError.
242 * Checks to see if the GError has been set. If the error has been
243 * set, then the glib.GError Python exception will be raised, and
244 * the GError cleared.
246 * Returns: True if an error was set.
249 pyglib_error_check(GError
**error
)
251 PyGILState_STATE state
;
253 PyObject
*exc_instance
;
256 g_return_val_if_fail(error
!= NULL
, FALSE
);
261 state
= pyglib_gil_state_ensure();
263 exc_type
= _PyGLib_API
->gerror_exception
;
264 if (exception_table
!= NULL
)
267 item
= PyDict_GetItem(exception_table
, _PyLong_FromLong((*error
)->domain
));
272 exc_instance
= PyObject_CallFunction(exc_type
, "z", (*error
)->message
);
274 if ((*error
)->domain
) {
275 PyObject_SetAttrString(exc_instance
, "domain",
276 d
=_PyUnicode_FromString(g_quark_to_string((*error
)->domain
)));
280 PyObject_SetAttrString(exc_instance
, "domain", Py_None
);
282 PyObject_SetAttrString(exc_instance
, "code",
283 d
=_PyLong_FromLong((*error
)->code
));
286 if ((*error
)->message
) {
287 PyObject_SetAttrString(exc_instance
, "message",
288 d
=_PyUnicode_FromString((*error
)->message
));
291 PyObject_SetAttrString(exc_instance
, "message", Py_None
);
294 PyErr_SetObject(_PyGLib_API
->gerror_exception
, exc_instance
);
295 Py_DECREF(exc_instance
);
296 g_clear_error(error
);
298 pyglib_gil_state_release(state
);
304 * pyglib_gerror_exception_check:
305 * @error: a standard GLib GError ** output parameter
307 * Checks to see if a GError exception has been raised, and if so
308 * translates the python exception to a standard GLib GError. If the
309 * raised exception is not a GError then PyErr_Print() is called.
311 * Returns: 0 if no exception has been raised, -1 if it is a
312 * valid glib.GError, -2 otherwise.
315 pyglib_gerror_exception_check(GError
**error
)
317 PyObject
*type
, *value
, *traceback
;
318 PyObject
*py_message
, *py_domain
, *py_code
;
319 const char *bad_gerror_message
;
321 PyErr_Fetch(&type
, &value
, &traceback
);
324 PyErr_NormalizeException(&type
, &value
, &traceback
);
326 PyErr_Restore(type
, value
, traceback
);
331 !PyErr_GivenExceptionMatches(type
,
332 (PyObject
*) _PyGLib_API
->gerror_exception
)) {
333 PyErr_Restore(type
, value
, traceback
);
338 Py_XDECREF(traceback
);
340 py_message
= PyObject_GetAttrString(value
, "message");
341 if (!py_message
|| !_PyUnicode_Check(py_message
)) {
342 bad_gerror_message
= "glib.GError instances must have a 'message' string attribute";
346 py_domain
= PyObject_GetAttrString(value
, "domain");
347 if (!py_domain
|| !_PyUnicode_Check(py_domain
)) {
348 bad_gerror_message
= "glib.GError instances must have a 'domain' string attribute";
349 Py_DECREF(py_message
);
353 py_code
= PyObject_GetAttrString(value
, "code");
354 if (!py_code
|| !_PyLong_Check(py_code
)) {
355 bad_gerror_message
= "glib.GError instances must have a 'code' int attribute";
356 Py_DECREF(py_message
);
357 Py_DECREF(py_domain
);
361 g_set_error(error
, g_quark_from_string(_PyUnicode_AsString(py_domain
)),
362 _PyLong_AsLong(py_code
), _PyUnicode_AsString(py_message
));
364 Py_DECREF(py_message
);
366 Py_DECREF(py_domain
);
371 g_set_error(error
, g_quark_from_static_string("pyglib"), 0, bad_gerror_message
);
372 PyErr_SetString(PyExc_ValueError
, bad_gerror_message
);
378 * pyglib_register_exception_for_domain:
379 * @name: name of the exception
380 * @error_domain: error domain
382 * Registers a new glib.GError exception subclass called #name for
383 * a specific #domain. This exception will be raised when a GError
384 * of the same domain is passed in to pyglib_error_check().
386 * Returns: the new exception
389 pyglib_register_exception_for_domain(gchar
*name
,
394 exception
= PyErr_NewException(name
, _PyGLib_API
->gerror_exception
, NULL
);
396 if (exception_table
== NULL
)
397 exception_table
= PyDict_New();
399 PyDict_SetItem(exception_table
,
400 _PyLong_FromLong(error_domain
),
407 * pyglib_main_context_new:
408 * @context: a GMainContext.
410 * Creates a wrapper for a GMainContext.
412 * Returns: the GMainContext wrapper.
415 pyglib_main_context_new(GMainContext
*context
)
417 PyGMainContext
*self
;
419 self
= (PyGMainContext
*)PyObject_NEW(PyGMainContext
,
420 &PyGMainContext_Type
);
424 self
->context
= g_main_context_ref(context
);
425 return (PyObject
*)self
;
429 * pyg_option_group_transfer_group:
430 * @group: a GOptionGroup wrapper
432 * This is used to transfer the GOptionGroup to a GOptionContext. After this
433 * is called, the calle must handle the release of the GOptionGroup.
435 * When #NULL is returned, the GOptionGroup was already transfered.
437 * Returns: Either #NULL or the wrapped GOptionGroup.
440 pyglib_option_group_transfer_group(PyObject
*obj
)
442 PyGOptionGroup
*self
= (PyGOptionGroup
*)obj
;
444 if (self
->is_in_context
)
447 self
->is_in_context
= TRUE
;
449 /* Here we increase the reference count of the PyGOptionGroup, because now
450 * the GOptionContext holds an reference to us (it is the userdata passed
451 * to g_option_group_new().
453 * The GOptionGroup is freed with the GOptionContext.
455 * We set it here because if we would do this in the init method we would
456 * hold two references and the PyGOptionGroup would never be freed.
464 * pyglib_option_group_new:
465 * @group: a GOptionGroup
467 * The returned GOptionGroup can't be used to set any hooks, translation domains
468 * or add entries. It's only intend is, to use for GOptionContext.add_group().
470 * Returns: the GOptionGroup wrapper.
473 pyglib_option_group_new (GOptionGroup
*group
)
475 PyGOptionGroup
*self
;
477 self
= (PyGOptionGroup
*)PyObject_NEW(PyGOptionGroup
,
478 &PyGOptionGroup_Type
);
483 self
->other_owner
= TRUE
;
484 self
->is_in_context
= FALSE
;
486 return (PyObject
*)self
;
490 * pyglib_option_context_new:
491 * @context: a GOptionContext
493 * Returns: A new GOptionContext wrapper.
496 pyglib_option_context_new (GOptionContext
*context
)
498 PyGOptionContext
*self
;
500 self
= (PyGOptionContext
*)PyObject_NEW(PyGOptionContext
,
501 &PyGOptionContext_Type
);
505 self
->context
= context
;
506 self
->main_group
= NULL
;
508 return (PyObject
*)self
;
512 * pyglib_option_context_new:
513 * @context: a GTimeVal struct
515 * Converts a GTimeVal struct to a python float
517 * Returns: a float representing the timeval
520 pyglib_float_from_timeval(GTimeVal timeval
)
523 ret
= (double)timeval
.tv_sec
+ (double)timeval
.tv_usec
* 0.000001;
524 return PyFloat_FromDouble(ret
);
528 /****** Private *****/
531 * _pyglib_destroy_notify:
532 * @user_data: a PyObject pointer.
534 * A function that can be used as a GDestroyNotify callback that will
535 * call Py_DECREF on the data.
538 _pyglib_destroy_notify(gpointer user_data
)
540 PyObject
*obj
= (PyObject
*)user_data
;
541 PyGILState_STATE state
;
543 g_return_if_fail (_PyGLib_API
!= NULL
);
545 state
= pyglib_gil_state_ensure();
547 pyglib_gil_state_release(state
);
551 _pyglib_handler_marshal(gpointer user_data
)
553 PyObject
*tuple
, *ret
;
555 PyGILState_STATE state
;
557 g_return_val_if_fail(user_data
!= NULL
, FALSE
);
559 state
= pyglib_gil_state_ensure();
561 tuple
= (PyObject
*)user_data
;
562 ret
= PyObject_CallObject(PyTuple_GetItem(tuple
, 0),
563 PyTuple_GetItem(tuple
, 1));
568 res
= PyObject_IsTrue(ret
);
572 pyglib_gil_state_release(state
);