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_closure_handle (ffi_cif *cif,
464 PyGILState_STATE state;
465 PyGICClosure *closure = data;
468 GIArgument *out_args = NULL;
470 /* Lock the GIL as we are coming into this code without the lock and we
471 may be executing python code */
472 state = PyGILState_Ensure();
474 if (!_pygi_closure_convert_arguments ( (GICallableInfo *) closure->info, args,
476 &py_args, &out_args)) {
477 if (PyErr_Occurred ())
482 retval = PyObject_CallObject ( (PyObject *) closure->function, py_args);
485 if (retval == NULL) {
490 _pygi_closure_set_out_arguments (closure->info, retval, out_args, result);
495 PyGILState_Release (state);
497 /* Now that the closure has finished we can make a decision about how
498 to free it. Scope call gets free'd at the end of wrap_g_function_info_invoke
499 scope notified will be freed, when the notify is called and we can free async
500 anytime we want as long as its after we return from this function (you can't free the closure
501 you are currently using!)
503 switch (closure->scope) {
504 case GI_SCOPE_TYPE_CALL:
505 case GI_SCOPE_TYPE_NOTIFIED:
507 case GI_SCOPE_TYPE_ASYNC:
508 /* Append this PyGICClosure to a list of closure that we will free
509 after we're done with this function invokation */
510 async_free_list = g_slist_prepend (async_free_list, closure);
513 g_error ("Invalid scope reached inside %s. Possibly a bad annotation?",
514 g_base_info_get_name (closure->info));
518 void _pygi_invoke_closure_free (gpointer data)
520 PyGILState_STATE state;
521 PyGICClosure* invoke_closure = (PyGICClosure *) data;
523 state = PyGILState_Ensure();
524 Py_DECREF (invoke_closure->function);
526 g_callable_info_free_closure (invoke_closure->info,
527 invoke_closure->closure);
529 if (invoke_closure->info)
530 g_base_info_unref ( (GIBaseInfo*) invoke_closure->info);
532 Py_XDECREF (invoke_closure->user_data);
533 PyGILState_Release (state);
535 g_slice_free (PyGICClosure, invoke_closure);
540 _pygi_make_native_closure (GICallableInfo* info,
542 PyObject *py_function,
543 gpointer py_user_data)
545 PyGICClosure *closure;
546 ffi_closure *fficlosure;
548 /* Begin by cleaning up old async functions */
549 g_slist_free_full (async_free_list, (GDestroyNotify) _pygi_invoke_closure_free);
550 async_free_list = NULL;
552 /* Build the closure itself */
553 closure = g_slice_new0 (PyGICClosure);
554 closure->info = (GICallableInfo *) g_base_info_ref ( (GIBaseInfo *) info);
555 closure->function = py_function;
556 closure->user_data = py_user_data;
558 Py_INCREF (py_function);
559 if (closure->user_data)
560 Py_INCREF (closure->user_data);
563 g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
565 closure->closure = fficlosure;
567 /* Give the closure the information it needs to determine when
568 to free itself later */
569 closure->scope = scope;