Imported Upstream version 3.9.91
[platform/upstream/python-gobject.git] / gi / pygi-closure.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * vim: tabstop=4 shiftwidth=4 expandtab
3  *
4  *   pygi-closure.c: PyGI C Closure functions
5  *
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.
10  *
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.
15  *
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
19  * USA
20  */
21
22 #include "pygi-private.h"
23
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.
27  */
28 static GSList* async_free_list;
29
30 static void
31 _pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
32                                       GITypeInfo *type_info,
33                                       GITransfer transfer)
34 {
35     GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
36     GITypeTag type_tag;
37     if (PyErr_Occurred ())
38         return;
39
40     type_tag = g_type_info_get_tag (type_info);
41
42     if (retval == NULL)
43         return;
44
45     switch (type_tag) {
46         case GI_TYPE_TAG_BOOLEAN:
47            *((ffi_sarg *) retval) = arg.v_boolean;
48            break;
49         case GI_TYPE_TAG_INT8:
50            *((ffi_sarg *) retval) = arg.v_int8;
51            break;
52         case GI_TYPE_TAG_UINT8:
53            *((ffi_arg *) retval) = arg.v_uint8;
54            break;
55         case GI_TYPE_TAG_INT16:
56            *((ffi_sarg *) retval) = arg.v_int16;
57            break;
58         case GI_TYPE_TAG_UINT16:
59            *((ffi_arg *) retval) = arg.v_uint16;
60            break;
61         case GI_TYPE_TAG_INT32:
62            *((ffi_sarg *) retval) = arg.v_int32;
63            break;
64         case GI_TYPE_TAG_UINT32:
65            *((ffi_arg *) retval) = arg.v_uint32;
66            break;
67         case GI_TYPE_TAG_INT64:
68            *((ffi_sarg *) retval) = arg.v_int64;
69            break;
70         case GI_TYPE_TAG_UINT64:
71            *((ffi_arg *) retval) = arg.v_uint64;
72            break;
73         case GI_TYPE_TAG_FLOAT:
74            *((gfloat *) retval) = arg.v_float;
75            break;
76         case GI_TYPE_TAG_DOUBLE:
77            *((gdouble *) retval) = arg.v_double;
78            break;
79         case GI_TYPE_TAG_GTYPE:
80            *((ffi_arg *) retval) = arg.v_ulong;
81            break;
82         case GI_TYPE_TAG_UNICHAR:
83             *((ffi_arg *) retval) = arg.v_uint32;
84             break;
85         case GI_TYPE_TAG_INTERFACE:
86             {
87                 GIBaseInfo* interface_info;
88                 GIInfoType interface_type;
89
90                 interface_info = g_type_info_get_interface(type_info);
91                 interface_type = g_base_info_get_type(interface_info);
92
93                 switch (interface_type) {
94                 case GI_INFO_TYPE_ENUM:
95                     *(ffi_sarg *) retval = arg.v_int;
96                     break;
97                 case GI_INFO_TYPE_FLAGS:
98                     *(ffi_arg *) retval = arg.v_uint;
99                     break;
100                 default:
101                     *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
102                     break;
103                 }
104
105                 g_base_info_unref (interface_info);
106                 break;
107             }
108         default:
109             *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
110             break;
111       }
112 }
113
114 static void
115 _pygi_closure_clear_retval (GICallableInfo *callable_info, gpointer retval)
116 {
117     GITypeInfo return_type_info;
118     GITypeTag return_type_tag;
119
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;
124     }
125 }
126
127 static void
128 _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
129                                             GITypeInfo *type_info,
130                                             GITransfer transfer)
131 {
132     GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
133     GITypeTag type_tag = g_type_info_get_tag (type_info);
134
135     if (out_arg == NULL)
136         return;
137
138     switch (type_tag) {
139         case GI_TYPE_TAG_BOOLEAN:
140            *((gboolean *) out_arg) = arg.v_boolean;
141            break;
142         case GI_TYPE_TAG_INT8:
143            *((gint8 *) out_arg) = arg.v_int8;
144            break;
145         case GI_TYPE_TAG_UINT8:
146            *((guint8 *) out_arg) = arg.v_uint8;
147            break;
148         case GI_TYPE_TAG_INT16:
149            *((gint16 *) out_arg) = arg.v_int16;
150            break;
151         case GI_TYPE_TAG_UINT16:
152            *((guint16 *) out_arg) = arg.v_uint16;
153            break;
154         case GI_TYPE_TAG_INT32:
155            *((gint32 *) out_arg) = arg.v_int32;
156            break;
157         case GI_TYPE_TAG_UINT32:
158            *((guint32 *) out_arg) = arg.v_uint32;
159            break;
160         case GI_TYPE_TAG_INT64:
161            *((gint64 *) out_arg) = arg.v_int64;
162            break;
163         case GI_TYPE_TAG_UINT64:
164            *((glong *) out_arg) = arg.v_uint64;
165            break;
166         case GI_TYPE_TAG_FLOAT:
167            *((gfloat *) out_arg) = arg.v_float;
168            break;
169         case GI_TYPE_TAG_DOUBLE:
170            *((gdouble *) out_arg) = arg.v_double;
171            break;
172         case GI_TYPE_TAG_GTYPE:
173            *((gulong *) out_arg) = arg.v_ulong;
174            break;
175         case GI_TYPE_TAG_UNICHAR:
176             *((guint32 *) out_arg) = arg.v_uint32;
177             break;
178         case GI_TYPE_TAG_INTERFACE:
179         {
180            GIBaseInfo *interface;
181            GIInfoType interface_type;
182
183            interface = g_type_info_get_interface (type_info);
184            interface_type = g_base_info_get_type (interface);
185
186            switch (interface_type) {
187            case GI_INFO_TYPE_ENUM:
188                *(gint *) out_arg = arg.v_int;
189                break;
190            case GI_INFO_TYPE_FLAGS:
191                *(guint *) out_arg = arg.v_uint;
192                break;
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);
198                    }
199                    break;
200                }
201
202            /* Fall through if pointer */
203            default:
204                *((gpointer *) out_arg) = arg.v_pointer;
205                break;
206            }
207
208            g_base_info_unref (interface);
209            break;
210         }
211
212         default:
213            *((gpointer *) out_arg) = arg.v_pointer;
214            break;
215       }
216 }
217
218 static GIArgument *
219 _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
220 {
221     gint num_args, i;
222     GIArgInfo arg_info;
223     GITypeInfo arg_type;
224     GITypeTag tag;
225     GIDirection direction;
226     GIArgument *g_args;
227
228     num_args = g_callable_info_get_n_args (callable_info);
229     g_args = g_new0 (GIArgument, num_args);
230
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);
236
237         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
238             g_args[i].v_pointer = * (gpointer *) args[i];
239         } else {
240             switch (tag) {
241                 case GI_TYPE_TAG_BOOLEAN:
242                     g_args[i].v_boolean = * (gboolean *) args[i];
243                     break;
244                 case GI_TYPE_TAG_INT8:
245                     g_args[i].v_int8 = * (gint8 *) args[i];
246                     break;
247                 case GI_TYPE_TAG_UINT8:
248                     g_args[i].v_uint8 = * (guint8 *) args[i];
249                     break;
250                 case GI_TYPE_TAG_INT16:
251                     g_args[i].v_int16 = * (gint16 *) args[i];
252                     break;
253                 case GI_TYPE_TAG_UINT16:
254                     g_args[i].v_uint16 = * (guint16 *) args[i];
255                     break;
256                 case GI_TYPE_TAG_INT32:
257                     g_args[i].v_int32 = * (gint32 *) args[i];
258                     break;
259                 case GI_TYPE_TAG_UINT32:
260                     g_args[i].v_uint32 = * (guint32 *) args[i];
261                     break;
262                 case GI_TYPE_TAG_INT64:
263                     g_args[i].v_int64 = * (glong *) args[i];
264                     break;
265                 case GI_TYPE_TAG_UINT64:
266                     g_args[i].v_uint64 = * (glong *) args[i];
267                     break;
268                 case GI_TYPE_TAG_FLOAT:
269                     g_args[i].v_float = * (gfloat *) args[i];
270                     break;
271                 case GI_TYPE_TAG_DOUBLE:
272                     g_args[i].v_double = * (gdouble *) args[i];
273                     break;
274                 case GI_TYPE_TAG_UTF8:
275                     g_args[i].v_string = * (gchar **) args[i];
276                     break;
277                 case GI_TYPE_TAG_INTERFACE:
278                 {
279                     GIBaseInfo *interface;
280                     GIInfoType interface_type;
281
282                     interface = g_type_info_get_interface (&arg_type);
283                     interface_type = g_base_info_get_type (interface);
284
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);
289                         break;
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);
294                         break;
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);
299                         break;
300                     }
301
302                     g_base_info_unref (interface);
303                 }
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];
311                     break;
312                 default:
313                     g_warning ("Unhandled type tag %s", g_type_tag_to_string (tag));
314                     g_args[i].v_pointer = 0;
315             }
316         }
317     }
318     return g_args;
319 }
320
321 static gboolean
322 _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
323                                  void *user_data, PyObject **py_args,
324                                  GIArgument **out_args)
325 {
326     int n_args = g_callable_info_get_n_args (callable_info);
327     int n_in_args = 0;
328     int n_out_args = 0;
329     int i;
330     int user_data_arg = -1;
331     int destroy_notify_arg = -1;
332
333     GIArgument *g_args = NULL;
334
335     *py_args = NULL;
336     *py_args = PyTuple_New (n_args);
337     if (*py_args == NULL)
338         goto error;
339
340     *out_args = NULL;
341     *out_args = g_new0 (GIArgument, n_args);
342     g_args = _pygi_closure_convert_ffi_arguments (callable_info, args);
343
344     for (i = 0; i < n_args; i++) {
345         GIArgInfo arg_info;
346         GIDirection direction;
347
348         /* Special case callbacks and skip over userdata and Destroy Notify */
349         if (i == user_data_arg || i == destroy_notify_arg)
350             continue;
351
352         g_callable_info_load_arg (callable_info, i, &arg_info);
353         direction = g_arg_info_get_direction (&arg_info);
354
355         if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
356             GITypeInfo arg_type;
357             GITypeTag arg_tag;
358             GITransfer transfer;
359             PyObject *value;
360             GIArgument *arg;
361             gboolean free_array;
362
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);
366             free_array = FALSE;
367
368             if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID &&
369                     g_type_info_is_pointer (&arg_type)) {
370
371                 if (user_data == NULL) {
372                     Py_INCREF (Py_None);
373                     value = Py_None;
374                 } else {
375                     value = user_data;
376                     Py_INCREF (value);
377                 }
378             } else if (direction == GI_DIRECTION_IN &&
379                        arg_tag == GI_TYPE_TAG_INTERFACE) {
380                 /* Handle callbacks as a special case */
381                 GIBaseInfo *info;
382                 GIInfoType info_type;
383
384                 info = g_type_info_get_interface (&arg_type);
385                 info_type = g_base_info_get_type (info);
386
387                 arg = (GIArgument*) &g_args[i];
388
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);
393
394                     user_data_arg = g_arg_info_get_closure(&arg_info);
395                     destroy_notify_arg = g_arg_info_get_destroy(&arg_info);
396
397                     if (user_data_arg != -1)
398                         user_data = g_args[user_data_arg].v_pointer;
399
400                     if (destroy_notify_arg != -1)
401                         user_data = (GDestroyNotify) g_args[destroy_notify_arg].v_pointer;
402
403                     value = _pygi_ccallback_new(arg->v_pointer,
404                                                 user_data,
405                                                 scope,
406                                                 (GIFunctionInfo *) info,
407                                                 destroy_notify);
408                 } else
409                     value = _pygi_argument_to_object (arg, &arg_type, transfer);
410
411                 g_base_info_unref (info);
412                 if (value == NULL)
413                     goto error;
414             } else {
415                 if (direction == GI_DIRECTION_IN)
416                     arg = (GIArgument*) &g_args[i];
417                 else
418                     arg = (GIArgument*) g_args[i].v_pointer;
419                 
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);
423
424                 value = _pygi_argument_to_object (arg, &arg_type, transfer);
425                 
426                 if (free_array)
427                     g_array_free (arg->v_pointer, FALSE);
428                 
429                 if (value == NULL)
430                     goto error;
431             }
432             PyTuple_SET_ITEM (*py_args, n_in_args, value);
433             n_in_args++;
434         }
435
436         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
437             (*out_args) [n_out_args] = g_args[i];
438             n_out_args++;
439         }
440
441     }
442
443     if (_PyTuple_Resize (py_args, n_in_args) == -1)
444         goto error;
445
446     g_free (g_args);
447     return TRUE;
448
449 error:
450     Py_CLEAR (*py_args);
451     g_free (*out_args);
452     *out_args = NULL;
453     g_free (g_args);
454
455     return FALSE;
456 }
457
458 static void
459 _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
460                                  PyObject *py_retval, GIArgument *out_args,
461                                  void *resp)
462 {
463     int n_args, i, i_py_retval, i_out_args;
464     GITypeInfo return_type_info;
465     GITypeTag return_type_tag;
466
467     i_py_retval = 0;
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);
476         } else {
477             _pygi_closure_assign_pyobj_to_retval (resp, py_retval,
478                 &return_type_info, transfer);
479         }
480         i_py_retval++;
481     }
482
483     i_out_args = 0;
484     n_args = g_callable_info_get_n_args (callable_info);
485     for (i = 0; i < n_args; i++) {
486         GIArgInfo arg_info;
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);
492
493         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
494             GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info);
495
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;
499                 i_out_args++;
500                 continue;
501             }
502
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,
510                     transfer);
511             } else
512                 g_assert_not_reached();
513
514             i_out_args++;
515             i_py_retval++;
516         }
517     }
518 }
519
520 static void
521 _pygi_invoke_closure_clear_py_data(PyGICClosure *invoke_closure)
522 {
523     PyGILState_STATE state = PyGILState_Ensure();
524
525     Py_CLEAR (invoke_closure->function);
526     Py_CLEAR (invoke_closure->user_data);
527
528     PyGILState_Release (state);
529 }
530
531 void
532 _pygi_closure_handle (ffi_cif *cif,
533                       void    *result,
534                       void   **args,
535                       void    *data)
536 {
537     PyGILState_STATE state;
538     PyGICClosure *closure = data;
539     PyObject *retval;
540     PyObject *py_args;
541     GIArgument *out_args = NULL;
542
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();
546
547     if (!_pygi_closure_convert_arguments ( (GICallableInfo *) closure->info, args,
548                                            closure->user_data,
549                                            &py_args, &out_args)) {
550         if (PyErr_Occurred ())
551             PyErr_Print();
552         goto end;
553     }
554
555     retval = PyObject_CallObject ( (PyObject *) closure->function, py_args);
556     Py_DECREF (py_args);
557
558     if (retval == NULL) {
559         _pygi_closure_clear_retval (closure->info, result);
560         PyErr_Print();
561         goto end;
562     }
563
564     _pygi_closure_set_out_arguments (closure->info, retval, out_args, result);
565     if (PyErr_Occurred ()) {
566         _pygi_closure_clear_retval (closure->info, result);
567         PyErr_Print();
568     }
569
570     Py_DECREF (retval);
571
572 end:
573     g_free (out_args);
574
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!)
582     */
583     switch (closure->scope) {
584         case GI_SCOPE_TYPE_CALL:
585         case GI_SCOPE_TYPE_NOTIFIED:
586             break;
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);
592             break;
593         default:
594             g_error ("Invalid scope reached inside %s.  Possibly a bad annotation?",
595                      g_base_info_get_name (closure->info));
596     }
597
598     PyGILState_Release (state);
599 }
600
601 void _pygi_invoke_closure_free (gpointer data)
602 {
603     PyGICClosure* invoke_closure = (PyGICClosure *) data;
604
605     g_callable_info_free_closure (invoke_closure->info,
606                                   invoke_closure->closure);
607
608     if (invoke_closure->info)
609         g_base_info_unref ( (GIBaseInfo*) invoke_closure->info);
610
611     _pygi_invoke_closure_clear_py_data(invoke_closure);
612
613     g_slice_free (PyGICClosure, invoke_closure);
614 }
615
616
617 PyGICClosure*
618 _pygi_make_native_closure (GICallableInfo* info,
619                            GIScopeType scope,
620                            PyObject *py_function,
621                            gpointer py_user_data)
622 {
623     PyGICClosure *closure;
624     ffi_closure *fficlosure;
625
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;
629
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;
635
636     Py_INCREF (py_function);
637     Py_INCREF (closure->user_data);
638
639     fficlosure =
640         g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
641                                          closure);
642     closure->closure = fficlosure;
643
644     /* Give the closure the information it needs to determine when
645        to free itself later */
646     closure->scope = scope;
647
648     return closure;
649 }