1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * pygi-closure.c: PyGI C Closure functions
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
22 #include "pygi-private.h"
24 /* This maintains a list of closures which can be free'd whenever
25 as they have been called. We will free them on the next
26 library function call.
28 static GSList* async_free_list;
31 _pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
32 GITypeInfo *type_info,
35 GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
37 if (PyErr_Occurred ())
40 type_tag = g_type_info_get_tag (type_info);
46 case GI_TYPE_TAG_BOOLEAN:
47 *((ffi_sarg *) retval) = arg.v_boolean;
49 case GI_TYPE_TAG_INT8:
50 *((ffi_sarg *) retval) = arg.v_int8;
52 case GI_TYPE_TAG_UINT8:
53 *((ffi_arg *) retval) = arg.v_uint8;
55 case GI_TYPE_TAG_INT16:
56 *((ffi_sarg *) retval) = arg.v_int16;
58 case GI_TYPE_TAG_UINT16:
59 *((ffi_arg *) retval) = arg.v_uint16;
61 case GI_TYPE_TAG_INT32:
62 *((ffi_sarg *) retval) = arg.v_int32;
64 case GI_TYPE_TAG_UINT32:
65 *((ffi_arg *) retval) = arg.v_uint32;
67 case GI_TYPE_TAG_INT64:
68 *((ffi_sarg *) retval) = arg.v_int64;
70 case GI_TYPE_TAG_UINT64:
71 *((ffi_arg *) retval) = arg.v_uint64;
73 case GI_TYPE_TAG_FLOAT:
74 *((gfloat *) retval) = arg.v_float;
76 case GI_TYPE_TAG_DOUBLE:
77 *((gdouble *) retval) = arg.v_double;
79 case GI_TYPE_TAG_GTYPE:
80 *((ffi_arg *) retval) = arg.v_ulong;
82 case GI_TYPE_TAG_UNICHAR:
83 *((ffi_arg *) retval) = arg.v_uint32;
85 case GI_TYPE_TAG_INTERFACE:
87 GIBaseInfo* interface_info;
88 GIInfoType interface_type;
90 interface_info = g_type_info_get_interface(type_info);
91 interface_type = g_base_info_get_type(interface_info);
93 switch (interface_type) {
94 case GI_INFO_TYPE_ENUM:
95 *(ffi_sarg *) retval = arg.v_int;
97 case GI_INFO_TYPE_FLAGS:
98 *(ffi_arg *) retval = arg.v_uint;
101 *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
105 g_base_info_unref (interface_info);
109 *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
115 _pygi_closure_clear_retval (GICallableInfo *callable_info, gpointer retval)
117 GITypeInfo return_type_info;
118 GITypeTag return_type_tag;
120 g_callable_info_load_return_type (callable_info, &return_type_info);
121 return_type_tag = g_type_info_get_tag (&return_type_info);
122 if (return_type_tag != GI_TYPE_TAG_VOID) {
123 *((ffi_arg *) retval) = 0;
128 _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
129 GITypeInfo *type_info,
132 GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
133 GITypeTag type_tag = g_type_info_get_tag (type_info);
139 case GI_TYPE_TAG_BOOLEAN:
140 *((gboolean *) out_arg) = arg.v_boolean;
142 case GI_TYPE_TAG_INT8:
143 *((gint8 *) out_arg) = arg.v_int8;
145 case GI_TYPE_TAG_UINT8:
146 *((guint8 *) out_arg) = arg.v_uint8;
148 case GI_TYPE_TAG_INT16:
149 *((gint16 *) out_arg) = arg.v_int16;
151 case GI_TYPE_TAG_UINT16:
152 *((guint16 *) out_arg) = arg.v_uint16;
154 case GI_TYPE_TAG_INT32:
155 *((gint32 *) out_arg) = arg.v_int32;
157 case GI_TYPE_TAG_UINT32:
158 *((guint32 *) out_arg) = arg.v_uint32;
160 case GI_TYPE_TAG_INT64:
161 *((gint64 *) out_arg) = arg.v_int64;
163 case GI_TYPE_TAG_UINT64:
164 *((glong *) out_arg) = arg.v_uint64;
166 case GI_TYPE_TAG_FLOAT:
167 *((gfloat *) out_arg) = arg.v_float;
169 case GI_TYPE_TAG_DOUBLE:
170 *((gdouble *) out_arg) = arg.v_double;
172 case GI_TYPE_TAG_GTYPE:
173 *((gulong *) out_arg) = arg.v_ulong;
175 case GI_TYPE_TAG_UNICHAR:
176 *((guint32 *) out_arg) = arg.v_uint32;
178 case GI_TYPE_TAG_INTERFACE:
180 GIBaseInfo *interface;
181 GIInfoType interface_type;
183 interface = g_type_info_get_interface (type_info);
184 interface_type = g_base_info_get_type (interface);
186 switch (interface_type) {
187 case GI_INFO_TYPE_ENUM:
188 *(gint *) out_arg = arg.v_int;
190 case GI_INFO_TYPE_FLAGS:
191 *(guint *) out_arg = arg.v_uint;
193 case GI_INFO_TYPE_STRUCT:
194 if (!g_type_info_is_pointer (type_info)) {
195 if (object != Py_None) {
196 gsize item_size = _pygi_g_type_info_size (type_info);
197 memcpy (out_arg, arg.v_pointer, item_size);
202 /* Fall through if pointer */
204 *((gpointer *) out_arg) = arg.v_pointer;
208 g_base_info_unref (interface);
213 *((gpointer *) out_arg) = arg.v_pointer;
219 _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
225 GIDirection direction;
228 num_args = g_callable_info_get_n_args (callable_info);
229 g_args = g_new0 (GIArgument, num_args);
231 for (i = 0; i < num_args; i++) {
232 g_callable_info_load_arg (callable_info, i, &arg_info);
233 g_arg_info_load_type (&arg_info, &arg_type);
234 tag = g_type_info_get_tag (&arg_type);
235 direction = g_arg_info_get_direction (&arg_info);
237 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
238 g_args[i].v_pointer = * (gpointer *) args[i];
241 case GI_TYPE_TAG_BOOLEAN:
242 g_args[i].v_boolean = * (gboolean *) args[i];
244 case GI_TYPE_TAG_INT8:
245 g_args[i].v_int8 = * (gint8 *) args[i];
247 case GI_TYPE_TAG_UINT8:
248 g_args[i].v_uint8 = * (guint8 *) args[i];
250 case GI_TYPE_TAG_INT16:
251 g_args[i].v_int16 = * (gint16 *) args[i];
253 case GI_TYPE_TAG_UINT16:
254 g_args[i].v_uint16 = * (guint16 *) args[i];
256 case GI_TYPE_TAG_INT32:
257 g_args[i].v_int32 = * (gint32 *) args[i];
259 case GI_TYPE_TAG_UINT32:
260 g_args[i].v_uint32 = * (guint32 *) args[i];
262 case GI_TYPE_TAG_INT64:
263 g_args[i].v_int64 = * (glong *) args[i];
265 case GI_TYPE_TAG_UINT64:
266 g_args[i].v_uint64 = * (glong *) args[i];
268 case GI_TYPE_TAG_FLOAT:
269 g_args[i].v_float = * (gfloat *) args[i];
271 case GI_TYPE_TAG_DOUBLE:
272 g_args[i].v_double = * (gdouble *) args[i];
274 case GI_TYPE_TAG_UTF8:
275 g_args[i].v_string = * (gchar **) args[i];
277 case GI_TYPE_TAG_INTERFACE:
279 GIBaseInfo *interface;
280 GIInfoType interface_type;
282 interface = g_type_info_get_interface (&arg_type);
283 interface_type = g_base_info_get_type (interface);
285 if (interface_type == GI_INFO_TYPE_OBJECT ||
286 interface_type == GI_INFO_TYPE_INTERFACE) {
287 g_args[i].v_pointer = * (gpointer *) args[i];
288 g_base_info_unref (interface);
290 } else if (interface_type == GI_INFO_TYPE_ENUM ||
291 interface_type == GI_INFO_TYPE_FLAGS) {
292 g_args[i].v_uint = * (guint *) args[i];
293 g_base_info_unref (interface);
295 } else if (interface_type == GI_INFO_TYPE_STRUCT ||
296 interface_type == GI_INFO_TYPE_CALLBACK) {
297 g_args[i].v_pointer = * (gpointer *) args[i];
298 g_base_info_unref (interface);
302 g_base_info_unref (interface);
304 case GI_TYPE_TAG_ERROR:
305 case GI_TYPE_TAG_GHASH:
306 case GI_TYPE_TAG_GLIST:
307 case GI_TYPE_TAG_GSLIST:
308 case GI_TYPE_TAG_ARRAY:
309 case GI_TYPE_TAG_VOID:
310 g_args[i].v_pointer = * (gpointer *) args[i];
313 g_warning ("Unhandled type tag %s", g_type_tag_to_string (tag));
314 g_args[i].v_pointer = 0;
322 _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
323 void *user_data, PyObject **py_args,
324 GIArgument **out_args)
326 int n_args = g_callable_info_get_n_args (callable_info);
330 int user_data_arg = -1;
331 int destroy_notify_arg = -1;
333 GIArgument *g_args = NULL;
336 *py_args = PyTuple_New (n_args);
337 if (*py_args == NULL)
341 *out_args = g_new0 (GIArgument, n_args);
342 g_args = _pygi_closure_convert_ffi_arguments (callable_info, args);
344 for (i = 0; i < n_args; i++) {
346 GIDirection direction;
348 /* Special case callbacks and skip over userdata and Destroy Notify */
349 if (i == user_data_arg || i == destroy_notify_arg)
352 g_callable_info_load_arg (callable_info, i, &arg_info);
353 direction = g_arg_info_get_direction (&arg_info);
355 if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
363 g_arg_info_load_type (&arg_info, &arg_type);
364 arg_tag = g_type_info_get_tag (&arg_type);
365 transfer = g_arg_info_get_ownership_transfer (&arg_info);
368 if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID &&
369 g_type_info_is_pointer (&arg_type)) {
371 if (user_data == NULL) {
378 } else if (direction == GI_DIRECTION_IN &&
379 arg_tag == GI_TYPE_TAG_INTERFACE) {
380 /* Handle callbacks as a special case */
382 GIInfoType info_type;
384 info = g_type_info_get_interface (&arg_type);
385 info_type = g_base_info_get_type (info);
387 arg = (GIArgument*) &g_args[i];
389 if (info_type == GI_INFO_TYPE_CALLBACK) {
390 gpointer user_data = NULL;
391 GDestroyNotify destroy_notify = NULL;
392 GIScopeType scope = g_arg_info_get_scope(&arg_info);
394 user_data_arg = g_arg_info_get_closure(&arg_info);
395 destroy_notify_arg = g_arg_info_get_destroy(&arg_info);
397 if (user_data_arg != -1)
398 user_data = g_args[user_data_arg].v_pointer;
400 if (destroy_notify_arg != -1)
401 user_data = (GDestroyNotify) g_args[destroy_notify_arg].v_pointer;
403 value = _pygi_ccallback_new(arg->v_pointer,
406 (GIFunctionInfo *) info,
409 value = _pygi_argument_to_object (arg, &arg_type, transfer);
411 g_base_info_unref (info);
415 if (direction == GI_DIRECTION_IN)
416 arg = (GIArgument*) &g_args[i];
418 arg = (GIArgument*) g_args[i].v_pointer;
420 if (g_type_info_get_tag (&arg_type) == GI_TYPE_TAG_ARRAY)
421 arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, NULL,
422 callable_info, &arg_type, &free_array);
424 value = _pygi_argument_to_object (arg, &arg_type, transfer);
427 g_array_free (arg->v_pointer, FALSE);
432 PyTuple_SET_ITEM (*py_args, n_in_args, value);
436 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
437 (*out_args) [n_out_args] = g_args[i];
443 if (_PyTuple_Resize (py_args, n_in_args) == -1)
459 _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
460 PyObject *py_retval, GIArgument *out_args,
463 int n_args, i, i_py_retval, i_out_args;
464 GITypeInfo return_type_info;
465 GITypeTag return_type_tag;
468 g_callable_info_load_return_type (callable_info, &return_type_info);
469 return_type_tag = g_type_info_get_tag (&return_type_info);
470 if (return_type_tag != GI_TYPE_TAG_VOID) {
471 GITransfer transfer = g_callable_info_get_caller_owns (callable_info);
472 if (PyTuple_Check (py_retval)) {
473 PyObject *item = PyTuple_GET_ITEM (py_retval, 0);
474 _pygi_closure_assign_pyobj_to_retval (resp, item,
475 &return_type_info, transfer);
477 _pygi_closure_assign_pyobj_to_retval (resp, py_retval,
478 &return_type_info, transfer);
484 n_args = g_callable_info_get_n_args (callable_info);
485 for (i = 0; i < n_args; i++) {
487 GITypeInfo type_info;
488 GIDirection direction;
489 g_callable_info_load_arg (callable_info, i, &arg_info);
490 g_arg_info_load_type (&arg_info, &type_info);
491 direction = g_arg_info_get_direction (&arg_info);
493 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
494 GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info);
496 if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ERROR) {
497 /* TODO: check if an exception has been set and convert it to a GError */
498 out_args[i_out_args].v_pointer = NULL;
503 if (PyTuple_Check (py_retval)) {
504 PyObject *item = PyTuple_GET_ITEM (py_retval, i_py_retval);
505 _pygi_closure_assign_pyobj_to_out_argument (
506 out_args[i_out_args].v_pointer, item, &type_info, transfer);
507 } else if (i_py_retval == 0) {
508 _pygi_closure_assign_pyobj_to_out_argument (
509 out_args[i_out_args].v_pointer, py_retval, &type_info,
512 g_assert_not_reached();
521 _pygi_invoke_closure_clear_py_data(PyGICClosure *invoke_closure)
523 PyGILState_STATE state = PyGILState_Ensure();
525 Py_CLEAR (invoke_closure->function);
526 Py_CLEAR (invoke_closure->user_data);
528 PyGILState_Release (state);
532 _pygi_closure_handle (ffi_cif *cif,
537 PyGILState_STATE state;
538 PyGICClosure *closure = data;
541 GIArgument *out_args = NULL;
543 /* Lock the GIL as we are coming into this code without the lock and we
544 may be executing python code */
545 state = PyGILState_Ensure();
547 if (!_pygi_closure_convert_arguments ( (GICallableInfo *) closure->info, args,
549 &py_args, &out_args)) {
550 if (PyErr_Occurred ())
555 retval = PyObject_CallObject ( (PyObject *) closure->function, py_args);
558 if (retval == NULL) {
559 _pygi_closure_clear_retval (closure->info, result);
564 _pygi_closure_set_out_arguments (closure->info, retval, out_args, result);
565 if (PyErr_Occurred ()) {
566 _pygi_closure_clear_retval (closure->info, result);
575 /* Now that the closure has finished we can make a decision about how
576 to free it. Scope call gets free'd at the end of wrap_g_function_info_invoke.
577 Scope notified will be freed when the notify is called.
578 Scope async closures free only their python data now and the closure later
579 during the next creation of a closure. This minimizes potential ref leaks
580 at least in regards to the python objects.
581 (you can't free the closure you are currently using!)
583 switch (closure->scope) {
584 case GI_SCOPE_TYPE_CALL:
585 case GI_SCOPE_TYPE_NOTIFIED:
587 case GI_SCOPE_TYPE_ASYNC:
588 /* Append this PyGICClosure to a list of closure that we will free
589 after we're done with this function invokation */
590 _pygi_invoke_closure_clear_py_data(closure);
591 async_free_list = g_slist_prepend (async_free_list, closure);
594 g_error ("Invalid scope reached inside %s. Possibly a bad annotation?",
595 g_base_info_get_name (closure->info));
598 PyGILState_Release (state);
601 void _pygi_invoke_closure_free (gpointer data)
603 PyGICClosure* invoke_closure = (PyGICClosure *) data;
605 g_callable_info_free_closure (invoke_closure->info,
606 invoke_closure->closure);
608 if (invoke_closure->info)
609 g_base_info_unref ( (GIBaseInfo*) invoke_closure->info);
611 _pygi_invoke_closure_clear_py_data(invoke_closure);
613 g_slice_free (PyGICClosure, invoke_closure);
618 _pygi_make_native_closure (GICallableInfo* info,
620 PyObject *py_function,
621 gpointer py_user_data)
623 PyGICClosure *closure;
624 ffi_closure *fficlosure;
626 /* Begin by cleaning up old async functions */
627 g_slist_free_full (async_free_list, (GDestroyNotify) _pygi_invoke_closure_free);
628 async_free_list = NULL;
630 /* Build the closure itself */
631 closure = g_slice_new0 (PyGICClosure);
632 closure->info = (GICallableInfo *) g_base_info_ref ( (GIBaseInfo *) info);
633 closure->function = py_function;
634 closure->user_data = py_user_data ? py_user_data : Py_None;
636 Py_INCREF (py_function);
637 Py_INCREF (closure->user_data);
640 g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
642 closure->closure = fficlosure;
644 /* Give the closure the information it needs to determine when
645 to free itself later */
646 closure->scope = scope;