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);
36 GITypeTag type_tag = g_type_info_get_tag (type_info);
42 case GI_TYPE_TAG_BOOLEAN:
43 *((ffi_sarg *) retval) = arg.v_boolean;
45 case GI_TYPE_TAG_INT8:
46 *((ffi_sarg *) retval) = arg.v_int8;
48 case GI_TYPE_TAG_UINT8:
49 *((ffi_arg *) retval) = arg.v_uint8;
51 case GI_TYPE_TAG_INT16:
52 *((ffi_sarg *) retval) = arg.v_int16;
54 case GI_TYPE_TAG_UINT16:
55 *((ffi_arg *) retval) = arg.v_uint16;
57 case GI_TYPE_TAG_INT32:
58 *((ffi_sarg *) retval) = arg.v_int32;
60 case GI_TYPE_TAG_UINT32:
61 *((ffi_arg *) retval) = arg.v_uint32;
63 case GI_TYPE_TAG_INT64:
64 *((ffi_sarg *) retval) = arg.v_int64;
66 case GI_TYPE_TAG_UINT64:
67 *((ffi_arg *) retval) = arg.v_uint64;
69 case GI_TYPE_TAG_FLOAT:
70 *((gfloat *) retval) = arg.v_float;
72 case GI_TYPE_TAG_DOUBLE:
73 *((gdouble *) retval) = arg.v_double;
76 *((GIArgument *) retval) = arg;
82 _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
83 GITypeInfo *type_info,
86 GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
87 GITypeTag type_tag = g_type_info_get_tag (type_info);
93 case GI_TYPE_TAG_BOOLEAN:
94 *((gboolean *) out_arg) = arg.v_boolean;
96 case GI_TYPE_TAG_INT8:
97 *((gint8 *) out_arg) = arg.v_int8;
99 case GI_TYPE_TAG_UINT8:
100 *((guint8 *) out_arg) = arg.v_uint8;
102 case GI_TYPE_TAG_INT16:
103 *((gint16 *) out_arg) = arg.v_int16;
105 case GI_TYPE_TAG_UINT16:
106 *((guint16 *) out_arg) = arg.v_uint16;
108 case GI_TYPE_TAG_INT32:
109 *((gint32 *) out_arg) = arg.v_int32;
111 case GI_TYPE_TAG_UINT32:
112 *((guint32 *) out_arg) = arg.v_uint32;
114 case GI_TYPE_TAG_INT64:
115 *((gint64 *) out_arg) = arg.v_int64;
117 case GI_TYPE_TAG_UINT64:
118 *((glong *) out_arg) = arg.v_uint64;
120 case GI_TYPE_TAG_FLOAT:
121 *((gfloat *) out_arg) = arg.v_float;
123 case GI_TYPE_TAG_DOUBLE:
124 *((gdouble *) out_arg) = arg.v_double;
126 case GI_TYPE_TAG_INTERFACE:
128 GIBaseInfo *interface;
129 GIInfoType interface_type;
131 interface = g_type_info_get_interface (type_info);
132 interface_type = g_base_info_get_type (interface);
134 if (!g_type_info_is_pointer (type_info) &&
135 interface_type == GI_INFO_TYPE_STRUCT) {
136 if (object == Py_None) {
137 arg.v_pointer = NULL;
139 gsize item_size = _pygi_g_type_info_size (type_info);
140 memcpy (out_arg, arg.v_pointer, item_size);
148 *((GIArgument *) out_arg) = arg;
154 _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
158 GITypeInfo *arg_type;
160 GIDirection direction;
163 num_args = g_callable_info_get_n_args (callable_info);
164 g_args = g_new0 (GIArgument, num_args);
166 for (i = 0; i < num_args; i++) {
167 arg_info = g_callable_info_get_arg (callable_info, i);
168 arg_type = g_arg_info_get_type (arg_info);
169 tag = g_type_info_get_tag (arg_type);
170 direction = g_arg_info_get_direction (arg_info);
172 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
173 g_args[i].v_pointer = * (gpointer *) args[i];
176 case GI_TYPE_TAG_BOOLEAN:
177 g_args[i].v_boolean = * (gboolean *) args[i];
179 case GI_TYPE_TAG_INT8:
180 g_args[i].v_int8 = * (gint8 *) args[i];
182 case GI_TYPE_TAG_UINT8:
183 g_args[i].v_uint8 = * (guint8 *) args[i];
185 case GI_TYPE_TAG_INT16:
186 g_args[i].v_int16 = * (gint16 *) args[i];
188 case GI_TYPE_TAG_UINT16:
189 g_args[i].v_uint16 = * (guint16 *) args[i];
191 case GI_TYPE_TAG_INT32:
192 g_args[i].v_int32 = * (gint32 *) args[i];
194 case GI_TYPE_TAG_UINT32:
195 g_args[i].v_uint32 = * (guint32 *) args[i];
197 case GI_TYPE_TAG_INT64:
198 g_args[i].v_int64 = * (glong *) args[i];
200 case GI_TYPE_TAG_UINT64:
201 g_args[i].v_uint64 = * (glong *) args[i];
203 case GI_TYPE_TAG_FLOAT:
204 g_args[i].v_float = * (gfloat *) args[i];
206 case GI_TYPE_TAG_DOUBLE:
207 g_args[i].v_double = * (gdouble *) args[i];
209 case GI_TYPE_TAG_UTF8:
210 g_args[i].v_string = * (gchar **) args[i];
212 case GI_TYPE_TAG_INTERFACE:
214 GIBaseInfo *interface;
215 GIInfoType interface_type;
217 interface = g_type_info_get_interface (arg_type);
218 interface_type = g_base_info_get_type (interface);
220 if (interface_type == GI_INFO_TYPE_OBJECT ||
221 interface_type == GI_INFO_TYPE_INTERFACE) {
222 g_args[i].v_pointer = * (gpointer *) args[i];
223 g_base_info_unref (interface);
225 } else if (interface_type == GI_INFO_TYPE_ENUM ||
226 interface_type == GI_INFO_TYPE_FLAGS) {
227 g_args[i].v_double = * (double *) args[i];
228 g_base_info_unref (interface);
230 } else if (interface_type == GI_INFO_TYPE_STRUCT ||
231 interface_type == GI_INFO_TYPE_CALLBACK) {
232 g_args[i].v_pointer = * (gpointer *) args[i];
233 g_base_info_unref (interface);
237 g_base_info_unref (interface);
239 case GI_TYPE_TAG_ERROR:
240 case GI_TYPE_TAG_GHASH:
241 case GI_TYPE_TAG_GLIST:
242 case GI_TYPE_TAG_GSLIST:
243 case GI_TYPE_TAG_ARRAY:
244 case GI_TYPE_TAG_VOID:
245 g_args[i].v_pointer = * (gpointer *) args[i];
248 g_warning ("Unhandled type tag %s", g_type_tag_to_string (tag));
249 g_args[i].v_pointer = 0;
252 g_base_info_unref ( (GIBaseInfo *) arg_info);
253 g_base_info_unref ( (GIBaseInfo *) arg_type);
259 _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
260 void *user_data, PyObject **py_args,
261 GIArgument **out_args)
263 int n_args = g_callable_info_get_n_args (callable_info);
267 int user_data_arg = -1;
268 int destroy_notify_arg = -1;
270 GIArgument *g_args = NULL;
273 *py_args = PyTuple_New (n_args);
274 if (*py_args == NULL)
278 *out_args = g_new0 (GIArgument, n_args);
279 g_args = _pygi_closure_convert_ffi_arguments (callable_info, args);
281 for (i = 0; i < n_args; i++) {
282 /* Special case callbacks and skip over userdata and Destroy Notify */
283 if (i == user_data_arg || i == destroy_notify_arg)
286 GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
287 GIDirection direction = g_arg_info_get_direction (arg_info);
289 if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
290 GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
291 GITypeTag arg_tag = g_type_info_get_tag (arg_type);
292 GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
295 gboolean free_array = FALSE;
297 if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID &&
298 g_type_info_is_pointer (arg_type)) {
300 if (user_data == NULL) {
307 } else if (direction == GI_DIRECTION_IN &&
308 arg_tag == GI_TYPE_TAG_INTERFACE) {
309 /* Handle callbacks as a special case */
311 GIInfoType info_type;
313 info = g_type_info_get_interface (arg_type);
314 info_type = g_base_info_get_type (info);
316 arg = (GIArgument*) &g_args[i];
318 if (info_type == GI_INFO_TYPE_CALLBACK) {
319 gpointer user_data = NULL;
320 GDestroyNotify destroy_notify = NULL;
321 GIScopeType scope = g_arg_info_get_scope(arg_info);
323 user_data_arg = g_arg_info_get_closure(arg_info);
324 destroy_notify_arg = g_arg_info_get_destroy(arg_info);
326 if (user_data_arg != -1)
327 user_data = g_args[user_data_arg].v_pointer;
329 if (destroy_notify_arg != -1)
330 user_data = (GDestroyNotify) g_args[destroy_notify_arg].v_pointer;
332 value = _pygi_ccallback_new(arg->v_pointer,
335 (GIFunctionInfo *) info,
338 value = _pygi_argument_to_object (arg, arg_type, transfer);
340 g_base_info_unref (info);
342 g_base_info_unref (arg_type);
343 g_base_info_unref (arg_info);
347 if (direction == GI_DIRECTION_IN)
348 arg = (GIArgument*) &g_args[i];
350 arg = (GIArgument*) g_args[i].v_pointer;
352 if (g_type_info_get_tag (arg_type) == GI_TYPE_TAG_ARRAY)
353 arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args,
354 callable_info, arg_type, &free_array);
356 value = _pygi_argument_to_object (arg, arg_type, transfer);
359 g_array_free (arg->v_pointer, FALSE);
362 g_base_info_unref (arg_type);
363 g_base_info_unref (arg_info);
367 PyTuple_SET_ITEM (*py_args, n_in_args, value);
370 g_base_info_unref (arg_type);
373 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
374 (*out_args) [n_out_args] = g_args[i];
378 g_base_info_unref (arg_info);
381 if (_PyTuple_Resize (py_args, n_in_args) == -1)
397 _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
398 PyObject *py_retval, GIArgument *out_args,
401 int n_args, i, i_py_retval, i_out_args;
402 GITypeInfo *return_type_info;
403 GITypeTag return_type_tag;
406 return_type_info = g_callable_info_get_return_type (callable_info);
407 return_type_tag = g_type_info_get_tag (return_type_info);
408 if (return_type_tag != GI_TYPE_TAG_VOID) {
409 GITransfer transfer = g_callable_info_get_caller_owns (callable_info);
410 if (PyTuple_Check (py_retval)) {
411 PyObject *item = PyTuple_GET_ITEM (py_retval, 0);
412 _pygi_closure_assign_pyobj_to_retval (resp, item,
413 return_type_info, transfer);
415 _pygi_closure_assign_pyobj_to_retval (resp, py_retval,
416 return_type_info, transfer);
420 g_base_info_unref (return_type_info);
423 n_args = g_callable_info_get_n_args (callable_info);
424 for (i = 1; i < n_args; i++) {
425 GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
426 GITypeInfo *type_info = g_arg_info_get_type (arg_info);
427 GIDirection direction = g_arg_info_get_direction (arg_info);
429 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
430 GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
432 if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ERROR) {
433 /* TODO: check if an exception has been set and convert it to a GError */
434 out_args[i_out_args].v_pointer = NULL;
439 if (PyTuple_Check (py_retval)) {
440 PyObject *item = PyTuple_GET_ITEM (py_retval, i_py_retval);
441 _pygi_closure_assign_pyobj_to_out_argument (
442 out_args[i_out_args].v_pointer, item, type_info, transfer);
443 } else if (i_py_retval == 0) {
444 _pygi_closure_assign_pyobj_to_out_argument (
445 out_args[i_out_args].v_pointer, py_retval, type_info,
448 g_assert_not_reached();
453 g_base_info_unref (type_info);
454 g_base_info_unref (arg_info);
459 _pygi_invoke_closure_clear_py_data(PyGICClosure *invoke_closure)
461 PyGILState_STATE state = PyGILState_Ensure();
463 if (invoke_closure->function != NULL) {
464 Py_DECREF (invoke_closure->function);
465 invoke_closure->function = NULL;
468 if (invoke_closure->user_data != NULL) {
469 Py_DECREF (invoke_closure->user_data);
470 invoke_closure->user_data = NULL;
473 PyGILState_Release (state);
477 _pygi_closure_handle (ffi_cif *cif,
482 PyGILState_STATE state;
483 PyGICClosure *closure = data;
486 GIArgument *out_args = NULL;
488 /* Lock the GIL as we are coming into this code without the lock and we
489 may be executing python code */
490 state = PyGILState_Ensure();
492 if (!_pygi_closure_convert_arguments ( (GICallableInfo *) closure->info, args,
494 &py_args, &out_args)) {
495 if (PyErr_Occurred ())
500 retval = PyObject_CallObject ( (PyObject *) closure->function, py_args);
503 if (retval == NULL) {
508 _pygi_closure_set_out_arguments (closure->info, retval, out_args, result);
514 PyGILState_Release (state);
516 /* Now that the closure has finished we can make a decision about how
517 to free it. Scope call gets free'd at the end of wrap_g_function_info_invoke.
518 Scope notified will be freed when the notify is called.
519 Scope async closures free only their python data now and the closure later
520 during the next creation of a closure. This minimizes potential ref leaks
521 at least in regards to the python objects.
522 (you can't free the closure you are currently using!)
524 switch (closure->scope) {
525 case GI_SCOPE_TYPE_CALL:
526 case GI_SCOPE_TYPE_NOTIFIED:
528 case GI_SCOPE_TYPE_ASYNC:
529 /* Append this PyGICClosure to a list of closure that we will free
530 after we're done with this function invokation */
531 _pygi_invoke_closure_clear_py_data(closure);
532 async_free_list = g_slist_prepend (async_free_list, closure);
535 g_error ("Invalid scope reached inside %s. Possibly a bad annotation?",
536 g_base_info_get_name (closure->info));
540 void _pygi_invoke_closure_free (gpointer data)
542 PyGICClosure* invoke_closure = (PyGICClosure *) data;
544 g_callable_info_free_closure (invoke_closure->info,
545 invoke_closure->closure);
547 if (invoke_closure->info)
548 g_base_info_unref ( (GIBaseInfo*) invoke_closure->info);
550 _pygi_invoke_closure_clear_py_data(invoke_closure);
552 g_slice_free (PyGICClosure, invoke_closure);
557 _pygi_make_native_closure (GICallableInfo* info,
559 PyObject *py_function,
560 gpointer py_user_data)
562 PyGICClosure *closure;
563 ffi_closure *fficlosure;
565 /* Begin by cleaning up old async functions */
566 g_slist_free_full (async_free_list, (GDestroyNotify) _pygi_invoke_closure_free);
567 async_free_list = NULL;
569 /* Build the closure itself */
570 closure = g_slice_new0 (PyGICClosure);
571 closure->info = (GICallableInfo *) g_base_info_ref ( (GIBaseInfo *) info);
572 closure->function = py_function;
573 closure->user_data = py_user_data ? py_user_data : Py_None;
575 Py_INCREF (py_function);
576 Py_INCREF (closure->user_data);
579 g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
581 closure->closure = fficlosure;
583 /* Give the closure the information it needs to determine when
584 to free itself later */
585 closure->scope = scope;