Imported Upstream version 3.7.3
[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 = g_type_info_get_tag (type_info);
37
38     if (retval == NULL)
39         return;
40
41     switch (type_tag) {
42         case GI_TYPE_TAG_BOOLEAN:
43            *((ffi_sarg *) retval) = arg.v_boolean;
44            break;
45         case GI_TYPE_TAG_INT8:
46            *((ffi_sarg *) retval) = arg.v_int8;
47            break;
48         case GI_TYPE_TAG_UINT8:
49            *((ffi_arg *) retval) = arg.v_uint8;
50            break;
51         case GI_TYPE_TAG_INT16:
52            *((ffi_sarg *) retval) = arg.v_int16;
53            break;
54         case GI_TYPE_TAG_UINT16:
55            *((ffi_arg *) retval) = arg.v_uint16;
56            break;
57         case GI_TYPE_TAG_INT32:
58            *((ffi_sarg *) retval) = arg.v_int32;
59            break;
60         case GI_TYPE_TAG_UINT32:
61            *((ffi_arg *) retval) = arg.v_uint32;
62            break;
63         case GI_TYPE_TAG_INT64:
64            *((ffi_sarg *) retval) = arg.v_int64;
65            break;
66         case GI_TYPE_TAG_UINT64:
67            *((ffi_arg *) retval) = arg.v_uint64;
68            break;
69         case GI_TYPE_TAG_FLOAT:
70            *((gfloat *) retval) = arg.v_float;
71            break;
72         case GI_TYPE_TAG_DOUBLE:
73            *((gdouble *) retval) = arg.v_double;
74            break;
75         default:
76            *((GIArgument *) retval) = arg;
77            break;
78       }
79 }
80
81 static void
82 _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
83                                             GITypeInfo *type_info,
84                                             GITransfer transfer)
85 {
86     GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
87     GITypeTag type_tag = g_type_info_get_tag (type_info);
88
89     if (out_arg == NULL)
90         return;
91
92     switch (type_tag) {
93         case GI_TYPE_TAG_BOOLEAN:
94            *((gboolean *) out_arg) = arg.v_boolean;
95            break;
96         case GI_TYPE_TAG_INT8:
97            *((gint8 *) out_arg) = arg.v_int8;
98            break;
99         case GI_TYPE_TAG_UINT8:
100            *((guint8 *) out_arg) = arg.v_uint8;
101            break;
102         case GI_TYPE_TAG_INT16:
103            *((gint16 *) out_arg) = arg.v_int16;
104            break;
105         case GI_TYPE_TAG_UINT16:
106            *((guint16 *) out_arg) = arg.v_uint16;
107            break;
108         case GI_TYPE_TAG_INT32:
109            *((gint32 *) out_arg) = arg.v_int32;
110            break;
111         case GI_TYPE_TAG_UINT32:
112            *((guint32 *) out_arg) = arg.v_uint32;
113            break;
114         case GI_TYPE_TAG_INT64:
115            *((gint64 *) out_arg) = arg.v_int64;
116            break;
117         case GI_TYPE_TAG_UINT64:
118            *((glong *) out_arg) = arg.v_uint64;
119            break;
120         case GI_TYPE_TAG_FLOAT:
121            *((gfloat *) out_arg) = arg.v_float;
122            break;
123         case GI_TYPE_TAG_DOUBLE:
124            *((gdouble *) out_arg) = arg.v_double;
125            break;
126         case GI_TYPE_TAG_INTERFACE:
127         {
128            GIBaseInfo *interface;
129            GIInfoType interface_type;
130
131            interface = g_type_info_get_interface (type_info);
132            interface_type = g_base_info_get_type (interface);
133
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;
138                } else {
139                    gsize item_size = _pygi_g_type_info_size (type_info);
140                    memcpy (out_arg, arg.v_pointer, item_size);
141                }
142                break;
143            }
144         }
145
146         /* Fall through */
147         default:
148            *((GIArgument *) out_arg) = arg;
149            break;
150       }
151 }
152
153 static GIArgument *
154 _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
155 {
156     gint num_args, i;
157     GIArgInfo *arg_info;
158     GITypeInfo *arg_type;
159     GITypeTag tag;
160     GIDirection direction;
161     GIArgument *g_args;
162
163     num_args = g_callable_info_get_n_args (callable_info);
164     g_args = g_new0 (GIArgument, num_args);
165
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);
171
172         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
173             g_args[i].v_pointer = * (gpointer *) args[i];
174         } else {
175             switch (tag) {
176                 case GI_TYPE_TAG_BOOLEAN:
177                     g_args[i].v_boolean = * (gboolean *) args[i];
178                     break;
179                 case GI_TYPE_TAG_INT8:
180                     g_args[i].v_int8 = * (gint8 *) args[i];
181                     break;
182                 case GI_TYPE_TAG_UINT8:
183                     g_args[i].v_uint8 = * (guint8 *) args[i];
184                     break;
185                 case GI_TYPE_TAG_INT16:
186                     g_args[i].v_int16 = * (gint16 *) args[i];
187                     break;
188                 case GI_TYPE_TAG_UINT16:
189                     g_args[i].v_uint16 = * (guint16 *) args[i];
190                     break;
191                 case GI_TYPE_TAG_INT32:
192                     g_args[i].v_int32 = * (gint32 *) args[i];
193                     break;
194                 case GI_TYPE_TAG_UINT32:
195                     g_args[i].v_uint32 = * (guint32 *) args[i];
196                     break;
197                 case GI_TYPE_TAG_INT64:
198                     g_args[i].v_int64 = * (glong *) args[i];
199                     break;
200                 case GI_TYPE_TAG_UINT64:
201                     g_args[i].v_uint64 = * (glong *) args[i];
202                     break;
203                 case GI_TYPE_TAG_FLOAT:
204                     g_args[i].v_float = * (gfloat *) args[i];
205                     break;
206                 case GI_TYPE_TAG_DOUBLE:
207                     g_args[i].v_double = * (gdouble *) args[i];
208                     break;
209                 case GI_TYPE_TAG_UTF8:
210                     g_args[i].v_string = * (gchar **) args[i];
211                     break;
212                 case GI_TYPE_TAG_INTERFACE:
213                 {
214                     GIBaseInfo *interface;
215                     GIInfoType interface_type;
216
217                     interface = g_type_info_get_interface (arg_type);
218                     interface_type = g_base_info_get_type (interface);
219
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);
224                         break;
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);
229                         break;
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);
234                         break;
235                     }
236
237                     g_base_info_unref (interface);
238                 }
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];
246                     break;
247                 default:
248                     g_warning ("Unhandled type tag %s", g_type_tag_to_string (tag));
249                     g_args[i].v_pointer = 0;
250             }
251         }
252         g_base_info_unref ( (GIBaseInfo *) arg_info);
253         g_base_info_unref ( (GIBaseInfo *) arg_type);
254     }
255     return g_args;
256 }
257
258 static gboolean
259 _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
260                                  void *user_data, PyObject **py_args,
261                                  GIArgument **out_args)
262 {
263     int n_args = g_callable_info_get_n_args (callable_info);
264     int n_in_args = 0;
265     int n_out_args = 0;
266     int i;
267     int user_data_arg = -1;
268     int destroy_notify_arg = -1;
269
270     GIArgument *g_args = NULL;
271
272     *py_args = NULL;
273     *py_args = PyTuple_New (n_args);
274     if (*py_args == NULL)
275         goto error;
276
277     *out_args = NULL;
278     *out_args = g_new0 (GIArgument, n_args);
279     g_args = _pygi_closure_convert_ffi_arguments (callable_info, args);
280
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)
284             continue;
285
286         GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
287         GIDirection direction = g_arg_info_get_direction (arg_info);
288
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);
293             PyObject *value;
294             GIArgument *arg;
295             gboolean free_array = FALSE;
296
297             if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID &&
298                     g_type_info_is_pointer (arg_type)) {
299
300                 if (user_data == NULL) {
301                     Py_INCREF (Py_None);
302                     value = Py_None;
303                 } else {
304                     value = user_data;
305                     Py_INCREF (value);
306                 }
307             } else if (direction == GI_DIRECTION_IN &&
308                        arg_tag == GI_TYPE_TAG_INTERFACE) {
309                 /* Handle callbacks as a special case */
310                 GIBaseInfo *info;
311                 GIInfoType info_type;
312
313                 info = g_type_info_get_interface (arg_type);
314                 info_type = g_base_info_get_type (info);
315
316                 arg = (GIArgument*) &g_args[i];
317
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);
322
323                     user_data_arg = g_arg_info_get_closure(arg_info);
324                     destroy_notify_arg = g_arg_info_get_destroy(arg_info);
325
326                     if (user_data_arg != -1)
327                         user_data = g_args[user_data_arg].v_pointer;
328
329                     if (destroy_notify_arg != -1)
330                         user_data = (GDestroyNotify) g_args[destroy_notify_arg].v_pointer;
331
332                     value = _pygi_ccallback_new(arg->v_pointer,
333                                                 user_data,
334                                                 scope,
335                                                 (GIFunctionInfo *) info,
336                                                 destroy_notify);
337                 } else
338                     value = _pygi_argument_to_object (arg, arg_type, transfer);
339
340                 g_base_info_unref (info);
341                 if (value == NULL) {
342                     g_base_info_unref (arg_type);
343                     g_base_info_unref (arg_info);
344                     goto error;
345                 }
346             } else {
347                 if (direction == GI_DIRECTION_IN)
348                     arg = (GIArgument*) &g_args[i];
349                 else
350                     arg = (GIArgument*) g_args[i].v_pointer;
351                 
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);
355
356                 value = _pygi_argument_to_object (arg, arg_type, transfer);
357                 
358                 if (free_array)
359                     g_array_free (arg->v_pointer, FALSE);
360                 
361                 if (value == NULL) {
362                     g_base_info_unref (arg_type);
363                     g_base_info_unref (arg_info);
364                     goto error;
365                 }
366             }
367             PyTuple_SET_ITEM (*py_args, n_in_args, value);
368             n_in_args++;
369
370             g_base_info_unref (arg_type);
371         }
372
373         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
374             (*out_args) [n_out_args] = g_args[i];
375             n_out_args++;
376         }
377
378         g_base_info_unref (arg_info);
379     }
380
381     if (_PyTuple_Resize (py_args, n_in_args) == -1)
382         goto error;
383
384     g_free (g_args);
385     return TRUE;
386
387 error:
388     Py_CLEAR (*py_args);
389     g_free (*out_args);
390     *out_args = NULL;
391     g_free (g_args);
392
393     return FALSE;
394 }
395
396 static void
397 _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
398                                  PyObject *py_retval, GIArgument *out_args,
399                                  void *resp)
400 {
401     int n_args, i, i_py_retval, i_out_args;
402     GITypeInfo *return_type_info;
403     GITypeTag return_type_tag;
404
405     i_py_retval = 0;
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);
414         } else {
415             _pygi_closure_assign_pyobj_to_retval (resp, py_retval,
416                 return_type_info, transfer);
417         }
418         i_py_retval++;
419     }
420     g_base_info_unref (return_type_info);
421
422     i_out_args = 0;
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);
428
429         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
430             GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
431
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;
435                 i_out_args++;
436                 continue;
437             }
438
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,
446                     transfer);
447             } else
448                 g_assert_not_reached();
449
450             i_out_args++;
451             i_py_retval++;
452         }
453         g_base_info_unref (type_info);
454         g_base_info_unref (arg_info);
455     }
456 }
457
458 static void
459 _pygi_invoke_closure_clear_py_data(PyGICClosure *invoke_closure)
460 {
461     PyGILState_STATE state = PyGILState_Ensure();
462
463     if (invoke_closure->function != NULL) {
464         Py_DECREF (invoke_closure->function);
465         invoke_closure->function = NULL;
466     }
467
468     if (invoke_closure->user_data != NULL) {
469         Py_DECREF (invoke_closure->user_data);
470         invoke_closure->user_data = NULL;
471     }
472
473     PyGILState_Release (state);
474 }
475
476 void
477 _pygi_closure_handle (ffi_cif *cif,
478                       void    *result,
479                       void   **args,
480                       void    *data)
481 {
482     PyGILState_STATE state;
483     PyGICClosure *closure = data;
484     PyObject *retval;
485     PyObject *py_args;
486     GIArgument *out_args = NULL;
487
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();
491
492     if (!_pygi_closure_convert_arguments ( (GICallableInfo *) closure->info, args,
493                                            closure->user_data,
494                                            &py_args, &out_args)) {
495         if (PyErr_Occurred ())
496             PyErr_Print();
497         goto end;
498     }
499
500     retval = PyObject_CallObject ( (PyObject *) closure->function, py_args);
501     Py_DECREF (py_args);
502
503     if (retval == NULL) {
504         PyErr_Print();
505         goto end;
506     }
507
508     _pygi_closure_set_out_arguments (closure->info, retval, out_args, result);
509     Py_DECREF (retval);
510
511 end:
512     g_free (out_args);
513
514     PyGILState_Release (state);
515
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!)
523     */
524     switch (closure->scope) {
525         case GI_SCOPE_TYPE_CALL:
526         case GI_SCOPE_TYPE_NOTIFIED:
527             break;
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);
533             break;
534         default:
535             g_error ("Invalid scope reached inside %s.  Possibly a bad annotation?",
536                      g_base_info_get_name (closure->info));
537     }
538 }
539
540 void _pygi_invoke_closure_free (gpointer data)
541 {
542     PyGICClosure* invoke_closure = (PyGICClosure *) data;
543
544     g_callable_info_free_closure (invoke_closure->info,
545                                   invoke_closure->closure);
546
547     if (invoke_closure->info)
548         g_base_info_unref ( (GIBaseInfo*) invoke_closure->info);
549
550     _pygi_invoke_closure_clear_py_data(invoke_closure);
551
552     g_slice_free (PyGICClosure, invoke_closure);
553 }
554
555
556 PyGICClosure*
557 _pygi_make_native_closure (GICallableInfo* info,
558                            GIScopeType scope,
559                            PyObject *py_function,
560                            gpointer py_user_data)
561 {
562     PyGICClosure *closure;
563     ffi_closure *fficlosure;
564
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;
568
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;
574
575     Py_INCREF (py_function);
576     Py_INCREF (closure->user_data);
577
578     fficlosure =
579         g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
580                                          closure);
581     closure->closure = fficlosure;
582
583     /* Give the closure the information it needs to determine when
584        to free itself later */
585     closure->scope = scope;
586
587     return closure;
588 }