1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * vim: tabstop=4 shiftwidth=4 expandtab
3  *
4  * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
5  *
6  *   pygi-invoke.c: main invocation function
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21  * USA
22  */
23 
24 #include <pyglib.h>
25 #include "pygi-invoke.h"
26 
27 struct invocation_state
28 {
29     gboolean is_method;
30     gboolean is_constructor;
31 
32     gsize n_args;
33     gsize n_in_args;
34     gsize n_out_args;
35     gsize n_backup_args;
36     Py_ssize_t n_py_args;
37     gsize n_aux_in_args;
38     gsize n_aux_out_args;
39     gsize n_return_values;
40 
41     guint8 callback_index;
42     guint8 user_data_index;
43     guint8 destroy_notify_index;
44     PyGICClosure *closure;
45 
46     glong error_arg_pos;
47 
48     GIArgInfo **arg_infos;
49     GITypeInfo **arg_type_infos;
50     GITypeInfo *return_type_info;
51     GITypeTag return_type_tag;
52 
53     GIArgument **args;
54     gboolean *args_is_auxiliary;
55 
56     GIArgument *in_args;
57     GIArgument *out_args;
58     GIArgument *out_values;
59     GIArgument *backup_args;
60     GIArgument return_arg;
61 
62     PyObject  *return_value;
63 
64     GType      implementor_gtype;
65 
66     /* hack to avoid treating C arrays as GArrays during free
67      * due to overly complicated array handling
68      * this will be removed when the new invoke branch is merged
69      */
70     gboolean c_arrays_are_wrapped;
71 };
72 
73 static gboolean
_initialize_invocation_state(struct invocation_state * state,GIFunctionInfo * info,PyObject * py_args,PyObject * kwargs)74 _initialize_invocation_state (struct invocation_state *state,
75                               GIFunctionInfo *info,
76                               PyObject *py_args,
77                               PyObject *kwargs)
78 {
79     if (g_base_info_get_type (info) == GI_INFO_TYPE_FUNCTION) {
80         GIFunctionInfoFlags flags = g_function_info_get_flags (info);
81 
82         state->is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
83         state->is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
84         state->implementor_gtype = 0;
85     } else {
86         PyObject *obj;
87 
88         state->is_method = TRUE;
89         state->is_constructor = FALSE;
90 
91         obj = PyDict_GetItemString (kwargs, "gtype");
92         if (obj == NULL) {
93             PyErr_SetString (PyExc_TypeError,
94                              "need the GType of the implementor class");
95             return FALSE;
96         }
97 
98         state->implementor_gtype = pyg_type_from_object (obj);
99         if (state->implementor_gtype == 0)
100             return FALSE;
101     }
102 
103     /* Count arguments. */
104     state->n_args = g_callable_info_get_n_args ( (GICallableInfo *) info);
105     state->n_in_args = 0;
106     state->n_out_args = 0;
107     state->n_backup_args = 0;
108     state->n_aux_in_args = 0;
109     state->n_aux_out_args = 0;
110 
111     /* Check the argument count. */
112     state->n_py_args = PyTuple_Size (py_args);
113     g_assert (state->n_py_args >= 0);
114 
115     state->error_arg_pos = -1;
116 
117     state->arg_infos = g_slice_alloc0 (sizeof (gpointer) * state->n_args);
118     state->arg_type_infos = g_slice_alloc0 (sizeof (gpointer) * state->n_args);
119     state->args_is_auxiliary = g_slice_alloc0 (sizeof (gboolean) * state->n_args);
120 
121     state->return_value = NULL;
122     state->closure = NULL;
123     state->return_type_info = NULL;
124     state->args = NULL;
125     state->in_args = NULL;
126     state->out_args = NULL;
127     state->out_values = NULL;
128     state->backup_args = NULL;
129 
130     /* HACK: this gets marked FALSE whenever a C array in the args is
131      *       not wrapped by a GArray
132      */
133     state->c_arrays_are_wrapped = TRUE;
134 
135     return TRUE;
136 }
137 
138 static gboolean
_prepare_invocation_state(struct invocation_state * state,GIFunctionInfo * function_info,PyObject * py_args)139 _prepare_invocation_state (struct invocation_state *state,
140                            GIFunctionInfo *function_info, PyObject *py_args)
141 {
142     gsize i;
143 
144     if (!_pygi_scan_for_callbacks (function_info,
145                                    state->is_method,
146                                    &state->callback_index, &state->user_data_index,
147                                    &state->destroy_notify_index))
148         return FALSE;
149 
150     if (state->callback_index != G_MAXUINT8) {
151 
152         if (!_pygi_create_callback (function_info,
153                                     state->is_method,
154                                     state->is_constructor,
155                                     state->n_args, state->n_py_args,
156                                     py_args, state->callback_index,
157                                     state->user_data_index,
158                                     state->destroy_notify_index, &state->closure))
159             return FALSE;
160 
161         state->args_is_auxiliary[state->callback_index] = FALSE;
162         if (state->destroy_notify_index != G_MAXUINT8) {
163             state->args_is_auxiliary[state->destroy_notify_index] = TRUE;
164             state->n_aux_in_args += 1;
165         }
166     }
167 
168     if (state->is_method) {
169         /* The first argument is the instance. */
170         state->n_in_args += 1;
171     }
172 
173     /* We do a first (well, second) pass here over the function to scan for special cases.
174      * This is currently array+length combinations, GError and GValue.
175      */
176     for (i = 0; i < state->n_args; i++) {
177         GIDirection direction;
178         GITransfer transfer;
179         GITypeTag arg_type_tag;
180 
181         state->arg_infos[i] = g_callable_info_get_arg ( (GICallableInfo *) function_info,
182                                                         i);
183 
184         state->arg_type_infos[i] = g_arg_info_get_type (state->arg_infos[i]);
185 
186         direction = g_arg_info_get_direction (state->arg_infos[i]);
187         transfer = g_arg_info_get_ownership_transfer (state->arg_infos[i]);
188         arg_type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
189 
190         if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
191             state->n_in_args += 1;
192         }
193         if (direction == GI_DIRECTION_INOUT) {
194             state->n_backup_args += 1;
195         }
196         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
197             state->n_out_args += 1;
198         }
199 
200         switch (arg_type_tag) {
201             case GI_TYPE_TAG_ARRAY:
202             {
203                 gint length_arg_pos;
204 
205                 length_arg_pos = g_type_info_get_array_length (state->arg_type_infos[i]);
206 
207                 if (length_arg_pos < 0) {
208                     break;
209                 }
210 
211                 /* For array lengths, we're going to delete the length argument;
212                  * so remove the extra backup we just added above */
213                 if (direction == GI_DIRECTION_INOUT) {
214                     state->n_backup_args -= 1;
215                 }
216 
217                 g_assert (length_arg_pos < state->n_args);
218                 state->args_is_auxiliary[length_arg_pos] = TRUE;
219 
220                 if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
221                     state->n_aux_in_args += 1;
222                 }
223                 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
224                     state->n_aux_out_args += 1;
225                 }
226 
227                 break;
228             }
229             case GI_TYPE_TAG_ERROR:
230                 g_warn_if_fail (state->error_arg_pos < 0);
231                 state->error_arg_pos = i;
232                 break;
233             default:
234                 break;
235         }
236     }
237 
238     state->return_type_info = g_callable_info_get_return_type ( (GICallableInfo *) function_info);
239     state->return_type_tag = g_type_info_get_tag (state->return_type_info);
240 
241     if (state->return_type_tag == GI_TYPE_TAG_ARRAY) {
242         gint length_arg_pos;
243         length_arg_pos = g_type_info_get_array_length (state->return_type_info);
244 
245         if (length_arg_pos >= 0) {
246             g_assert (length_arg_pos < state->n_args);
247             state->args_is_auxiliary[length_arg_pos] = TRUE;
248             state->n_aux_out_args += 1;
249         }
250     }
251 
252     state->n_return_values = state->n_out_args - state->n_aux_out_args;
253     if (state->return_type_tag != GI_TYPE_TAG_VOID) {
254         state->n_return_values += 1;
255     }
256 
257     {
258         gsize n_py_args_expected;
259         Py_ssize_t py_args_pos;
260 
261         n_py_args_expected = state->n_in_args
262                              + (state->is_constructor ? 1 : 0)
263                              - state->n_aux_in_args
264                              - (state->error_arg_pos >= 0 ? 1 : 0);
265 
266         if (state->n_py_args != n_py_args_expected) {
267             PyErr_Format (PyExc_TypeError,
268                           "%s() takes exactly %zd argument(s) (%zd given)",
269                           g_base_info_get_name ( (GIBaseInfo *) function_info),
270                           n_py_args_expected, state->n_py_args);
271             return FALSE;
272         }
273 
274         /* Check argument typestate-> */
275         py_args_pos = 0;
276         if (state->is_constructor || state->is_method) {
277             py_args_pos += 1;
278         }
279 
280         for (i = 0; i < state->n_args; i++) {
281             GIDirection direction;
282             GITypeTag type_tag;
283             PyObject *py_arg;
284             gint retval;
285             gboolean allow_none;
286 
287             direction = g_arg_info_get_direction (state->arg_infos[i]);
288             type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
289 
290             if (direction == GI_DIRECTION_OUT
291                     || state->args_is_auxiliary[i]
292                     || type_tag == GI_TYPE_TAG_ERROR) {
293                 continue;
294             }
295 
296             g_assert (py_args_pos < state->n_py_args);
297             py_arg = PyTuple_GET_ITEM (py_args, py_args_pos);
298 
299             allow_none = g_arg_info_may_be_null (state->arg_infos[i]);
300 
301             retval = _pygi_g_type_info_check_object (state->arg_type_infos[i],
302                                                      py_arg,
303                                                      allow_none);
304 
305             if (retval < 0) {
306                 return FALSE;
307             } else if (!retval) {
308                 _PyGI_ERROR_PREFIX ("argument %zd: ", py_args_pos);
309                 return FALSE;
310             }
311 
312             py_args_pos += 1;
313         }
314 
315         g_assert (py_args_pos == state->n_py_args);
316     }
317 
318     state->args = g_slice_alloc0 (sizeof (gpointer) * state->n_args);
319     state->in_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_in_args);
320     state->out_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_out_args);
321     state->out_values = g_slice_alloc0 (sizeof (GIArgument) * state->n_out_args);
322     state->backup_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_backup_args);
323 
324     /* Bind args so we can use an unique index. */
325     {
326         gsize in_args_pos;
327         gsize out_args_pos;
328 
329         in_args_pos = state->is_method ? 1 : 0;
330         out_args_pos = 0;
331 
332         for (i = 0; i < state->n_args; i++) {
333             GIDirection direction;
334             GIBaseInfo *info;
335             gboolean is_caller_allocates;
336 
337             direction = g_arg_info_get_direction (state->arg_infos[i]);
338             is_caller_allocates = g_arg_info_is_caller_allocates (state->arg_infos[i]);
339 
340             switch (direction) {
341                 case GI_DIRECTION_IN:
342                     g_assert (in_args_pos < state->n_in_args);
343                     state->args[i] = &state->in_args[in_args_pos];
344                     in_args_pos += 1;
345                     break;
346                 case GI_DIRECTION_INOUT:
347                     g_assert (in_args_pos < state->n_in_args);
348                     g_assert (out_args_pos < state->n_out_args);
349 
350                     state->in_args[in_args_pos].v_pointer = &state->out_values[out_args_pos];
351                     in_args_pos += 1;
352                 case GI_DIRECTION_OUT:
353                     g_assert (out_args_pos < state->n_out_args);
354 
355                     /* caller allocates only applies to structures but GI has
356                      * no way to denote that yet, so we only use caller allocates
357                      * if we see  a structure
358                      */
359                     if (is_caller_allocates) {
360                         GITypeTag type_tag;
361 
362                         is_caller_allocates = FALSE;
363                         type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
364 
365                         if (type_tag  == GI_TYPE_TAG_INTERFACE) {
366                             GIInfoType info_type;
367 
368                             info = g_type_info_get_interface (state->arg_type_infos[i]);
369                             g_assert (info != NULL);
370                             info_type = g_base_info_get_type (info);
371 
372                             if (info_type == GI_INFO_TYPE_STRUCT)
373                                 is_caller_allocates = TRUE;
374                         }
375                     }
376 
377                     if (is_caller_allocates) {
378                         /* if caller allocates only use one level of indirection */
379                         state->out_args[out_args_pos].v_pointer = NULL;
380                         state->args[i] = &state->out_args[out_args_pos];
381                         if (g_struct_info_is_foreign((GIStructInfo *) info) ) {
382                             PyObject *foreign_struct =
383                                 pygi_struct_foreign_convert_from_g_argument(info, NULL);
384 
385                             pygi_struct_foreign_convert_to_g_argument(
386                                 foreign_struct,
387                                 info,
388                                 GI_TRANSFER_EVERYTHING,
389                                 state->args[i]);
390 
391                             Py_DECREF(foreign_struct);
392                         } else if (g_type_is_a (g_registered_type_info_get_g_type (info), G_TYPE_BOXED)) {
393                             state->args[i]->v_pointer = _pygi_boxed_alloc (info, NULL);
394                         } else {
395                             gssize size = g_struct_info_get_size ( (GIStructInfo *) info);
396                             state->args[i]->v_pointer = g_malloc0 (size);
397                         }
398                     } else {
399                         state->out_args[out_args_pos].v_pointer = &state->out_values[out_args_pos];
400                         state->out_values[out_args_pos].v_pointer = NULL;
401                         state->args[i] = &state->out_values[out_args_pos];
402                     }
403 
404                     out_args_pos += 1;
405             }
406         }
407 
408         g_assert (in_args_pos == state->n_in_args);
409         g_assert (out_args_pos == state->n_out_args);
410     }
411 
412     /* Convert the input arguments. */
413     {
414         Py_ssize_t py_args_pos;
415         gsize backup_args_pos;
416 
417         py_args_pos = 0;
418         backup_args_pos = 0;
419 
420         if (state->is_constructor) {
421             /* Skip the first argument. */
422             py_args_pos += 1;
423         } else if (state->is_method) {
424             /* Get the instance. */
425             GIBaseInfo *container_info;
426             GIInfoType container_info_type;
427             PyObject *py_arg;
428             gint check_val;
429 
430             container_info = g_base_info_get_container (function_info);
431             container_info_type = g_base_info_get_type (container_info);
432 
433             g_assert (py_args_pos < state->n_py_args);
434             py_arg = PyTuple_GET_ITEM (py_args, py_args_pos);
435 
436             /* In python 2 python takes care of checking the type
437              * of the self instance.  In python 3 it does not
438              * so we have to check it here
439              */
440             check_val = _pygi_g_type_interface_check_object(container_info,
441                                                             py_arg);
442             if (check_val < 0) {
443                 return FALSE;
444             } else if (!check_val) {
445                 _PyGI_ERROR_PREFIX ("instance: ");
446                 return FALSE;
447             }
448 
449             switch (container_info_type) {
450                 case GI_INFO_TYPE_UNION:
451                 case GI_INFO_TYPE_STRUCT:
452                 {
453                     GType type;
454 
455                     type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) container_info);
456 
457                     if (g_type_is_a (type, G_TYPE_BOXED)) {
458                         g_assert (state->n_in_args > 0);
459                         state->in_args[0].v_pointer = pyg_boxed_get (py_arg, void);
460                     } else if (g_struct_info_is_foreign (container_info)) {
461                         PyObject *result;
462                         result = pygi_struct_foreign_convert_to_g_argument (
463                                      py_arg, container_info,
464                                      GI_TRANSFER_NOTHING,
465                                      &state->in_args[0]);
466                     } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
467                         g_assert (state->n_in_args > 0);
468                         state->in_args[0].v_pointer = pyg_pointer_get (py_arg, void);
469                     } else {
470                         PyErr_Format (PyExc_TypeError, "unable to convert an instance of '%s'", g_type_name (type));
471                         return FALSE;
472                     }
473 
474                     break;
475                 }
476                 case GI_INFO_TYPE_OBJECT:
477                 case GI_INFO_TYPE_INTERFACE:
478                     g_assert (state->n_in_args > 0);
479                     state->in_args[0].v_pointer = pygobject_get (py_arg);
480                     break;
481                 default:
482                     /* Other types don't have methods. */
483                     g_assert_not_reached();
484             }
485 
486             py_args_pos += 1;
487         }
488 
489         for (i = 0; i < state->n_args; i++) {
490             GIDirection direction;
491 
492             if (i == state->callback_index) {
493                 if (state->closure)
494                     state->args[i]->v_pointer = state->closure->closure;
495                 else
496                     /* Some callbacks params accept NULL */
497                     state->args[i]->v_pointer = NULL;
498                 py_args_pos++;
499                 continue;
500             } else if (i == state->user_data_index) {
501                 state->args[i]->v_pointer = state->closure;
502                 py_args_pos++;
503                 continue;
504             } else if (i == state->destroy_notify_index) {
505                 if (state->closure) {
506                     /* No need to clean up if the callback is NULL */
507                     PyGICClosure *destroy_notify = _pygi_destroy_notify_create();
508                     state->args[i]->v_pointer = destroy_notify->closure;
509                 }
510                 continue;
511             }
512 
513             if (state->args_is_auxiliary[i]) {
514                 continue;
515             }
516 
517             direction = g_arg_info_get_direction (state->arg_infos[i]);
518 
519             if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
520                 PyObject *py_arg;
521                 GITypeTag arg_type_tag;
522                 GITransfer transfer;
523 
524                 arg_type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
525 
526                 if (arg_type_tag == GI_TYPE_TAG_ERROR) {
527                     GError **error;
528 
529                     error = g_slice_new (GError *);
530                     *error = NULL;
531 
532                     state->args[i]->v_pointer = error;
533                     continue;
534                 }
535 
536                 transfer = g_arg_info_get_ownership_transfer (state->arg_infos[i]);
537 
538                 g_assert (py_args_pos < state->n_py_args);
539                 py_arg = PyTuple_GET_ITEM (py_args, py_args_pos);
540 
541                 *state->args[i] = _pygi_argument_from_object (py_arg, state->arg_type_infos[i], transfer);
542 
543                 if (PyErr_Occurred()) {
544                     /* TODO: release previous input arguments. */
545                     return FALSE;
546                 }
547 
548                 if (direction == GI_DIRECTION_INOUT) {
549                     /* We need to keep a copy of the argument to be able to release it later. */
550                     g_assert (backup_args_pos < state->n_backup_args);
551                     state->backup_args[backup_args_pos] = *state->args[i];
552                     backup_args_pos += 1;
553                 }
554 
555                 if (arg_type_tag == GI_TYPE_TAG_ARRAY) {
556                     GArray *array;
557                     gssize length_arg_pos;
558 
559                     array = state->args[i]->v_pointer;
560 
561                     length_arg_pos = g_type_info_get_array_length (state->arg_type_infos[i]);
562                     if (length_arg_pos >= 0) {
563                         int len = 0;
564                         /* Set the auxiliary argument holding the length. */
565                         if (array)
566                             len = array->len;
567 
568                         state->args[length_arg_pos]->v_size = len;
569                     }
570 
571                     /* Get rid of the GArray. */
572                     if ( (array != NULL) &&
573                             (g_type_info_get_array_type (state->arg_type_infos[i]) == GI_ARRAY_TYPE_C)) {
574                         state->args[i]->v_pointer = array->data;
575 
576                         /* HACK: We have unwrapped a C array so
577                          *       set the state to reflect this.
578                          *       If there is an error between now
579                          *       and when we rewrap the array
580                          *       we will leak C arrays due to
581                          *       being in an inconsitant state.
582                          *       e.g. for interfaces with more
583                          *       than one C array argument, an
584                          *       error may occure when not all
585                          *       C arrays have been rewrapped.
586                          *       This will be removed once the invoke
587                          *       rewrite branch is merged.
588                          */
589                         state->c_arrays_are_wrapped = FALSE;
590                         if (direction != GI_DIRECTION_INOUT || transfer != GI_TRANSFER_NOTHING) {
591                             /* The array hasn't been referenced anywhere, so free it to avoid losing memory. */
592                             g_array_free (array, FALSE);
593                         }
594                     }
595                 }
596 
597                 py_args_pos += 1;
598             }
599         }
600 
601         g_assert (py_args_pos == state->n_py_args);
602         g_assert (backup_args_pos == state->n_backup_args);
603     }
604 
605     return TRUE;
606 }
607 
608 static gboolean
_invoke_function(struct invocation_state * state,GICallableInfo * callable_info,PyObject * py_args)609 _invoke_function (struct invocation_state *state,
610                   GICallableInfo *callable_info, PyObject *py_args)
611 {
612     GError *error;
613     gint retval;
614 
615     error = NULL;
616 
617     pyg_begin_allow_threads;
618     if (g_base_info_get_type (callable_info) == GI_INFO_TYPE_FUNCTION) {
619         retval = g_function_info_invoke ( (GIFunctionInfo *) callable_info,
620                                           state->in_args,
621                                           state->n_in_args,
622                                           state->out_args,
623                                           state->n_out_args,
624                                           &state->return_arg,
625                                           &error);
626     } else {
627         retval = g_vfunc_info_invoke ( (GIVFuncInfo *) callable_info,
628                                        state->implementor_gtype,
629                                        state->in_args,
630                                        state->n_in_args,
631                                        state->out_args,
632                                        state->n_out_args,
633                                        &state->return_arg,
634                                        &error);
635     }
636     pyg_end_allow_threads;
637 
638     if (!retval) {
639         pyglib_error_check(&error);
640 
641         /* TODO: release input arguments. */
642 
643         return FALSE;
644     }
645 
646     if (state->error_arg_pos >= 0) {
647         GError **error;
648 
649         error = state->args[state->error_arg_pos]->v_pointer;
650 
651         if (pyglib_error_check(error)) {
652             /* TODO: release input arguments. */
653 
654             return FALSE;
655         }
656     }
657 
658     return TRUE;
659 }
660 
661 static gboolean
_process_invocation_state(struct invocation_state * state,GIFunctionInfo * function_info,PyObject * py_args)662 _process_invocation_state (struct invocation_state *state,
663                            GIFunctionInfo *function_info, PyObject *py_args)
664 {
665     gsize i;
666 
667     /* Convert the return value. */
668     if (state->is_constructor) {
669         PyTypeObject *py_type;
670         GIBaseInfo *info;
671         GIInfoType info_type;
672         GITransfer transfer;
673 
674         if (state->return_arg.v_pointer == NULL) {
675             PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
676             return FALSE;
677         }
678 
679         g_assert (state->n_py_args > 0);
680         py_type = (PyTypeObject *) PyTuple_GET_ITEM (py_args, 0);
681 
682         info = g_type_info_get_interface (state->return_type_info);
683         g_assert (info != NULL);
684 
685         info_type = g_base_info_get_type (info);
686 
687         transfer = g_callable_info_get_caller_owns ( (GICallableInfo *) function_info);
688 
689         switch (info_type) {
690             case GI_INFO_TYPE_UNION:
691             case GI_INFO_TYPE_STRUCT:
692             {
693                 GType type;
694 
695                 type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
696 
697                 if (g_struct_info_is_foreign (info)) {
698                     state->return_value =
699                         pygi_struct_foreign_convert_from_g_argument (
700                             info, state->return_arg.v_pointer);
701                 } else if (g_type_is_a (type, G_TYPE_BOXED)) {
702                     g_warn_if_fail (transfer == GI_TRANSFER_EVERYTHING);
703                     state->return_value = _pygi_boxed_new (py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
704                 } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
705                     if (transfer != GI_TRANSFER_NOTHING)
706                         g_warning ("Return argument in %s returns a struct "
707                                    "with a transfer mode of \"full\" "
708                                    "Transfer mode should be set to None for "
709                                    "struct types as there is no way to free "
710                                    "them safely.  Ignoring transfer mode "
711                                    "to prevent a potential invalid free. "
712                                    "This may cause a leak in your application.",
713                                    g_base_info_get_name ( (GIBaseInfo *) function_info) );
714 
715                     state->return_value = _pygi_struct_new (py_type, state->return_arg.v_pointer, FALSE);
716                 } else {
717                     PyErr_Format (PyExc_TypeError, "cannot create '%s' instances", py_type->tp_name);
718                     g_base_info_unref (info);
719                     return FALSE;
720                 }
721 
722                 break;
723             }
724             case GI_INFO_TYPE_OBJECT:
725                 if (state->return_arg.v_pointer == NULL) {
726                     PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
727                     break;
728                 }
729                 state->return_value = pygobject_new (state->return_arg.v_pointer);
730                 if (transfer == GI_TRANSFER_EVERYTHING) {
731                     /* The new wrapper increased the reference count, so decrease it. */
732                     g_object_unref (state->return_arg.v_pointer);
733                 }
734                 if (state->is_constructor && G_IS_INITIALLY_UNOWNED (state->return_arg.v_pointer)) {
735                     /* GInitiallyUnowned constructors always end up with one extra reference, so decrease it. */
736                     g_object_unref (state->return_arg.v_pointer);
737                 }
738                 break;
739             default:
740                 /* Other types don't have neither methods nor constructors. */
741                 g_assert_not_reached();
742         }
743 
744         g_base_info_unref (info);
745 
746         if (state->return_value == NULL) {
747             /* TODO: release arguments. */
748             return FALSE;
749         }
750     } else {
751         GITransfer transfer;
752 
753         if ( (state->return_type_tag == GI_TYPE_TAG_ARRAY) &&
754                 (g_type_info_get_array_type (state->return_type_info) == GI_ARRAY_TYPE_C)) {
755             /* Create a #GArray. */
756             state->return_arg.v_pointer = _pygi_argument_to_array (&state->return_arg, state->args, state->return_type_info, state->is_method);
757         }
758 
759         transfer = g_callable_info_get_caller_owns ( (GICallableInfo *) function_info);
760 
761         state->return_value = _pygi_argument_to_object (&state->return_arg, state->return_type_info, transfer);
762         if (state->return_value == NULL) {
763             /* TODO: release argument. */
764             return FALSE;
765         }
766 
767         _pygi_argument_release (&state->return_arg, state->return_type_info, transfer, GI_DIRECTION_OUT);
768 
769         if (state->return_type_tag == GI_TYPE_TAG_ARRAY
770                 && transfer == GI_TRANSFER_NOTHING) {
771             /* We created a #GArray, so free it. */
772             state->return_arg.v_pointer = g_array_free (state->return_arg.v_pointer, FALSE);
773         }
774     }
775 
776     /* Convert output arguments and release arguments. */
777     {
778         gsize return_values_pos;
779 
780         return_values_pos = 0;
781 
782         if (state->n_return_values > 1) {
783             /* Return a tuple. */
784             PyObject *return_values;
785 
786             return_values = PyTuple_New (state->n_return_values);
787             if (return_values == NULL) {
788                 /* TODO: release arguments. */
789                 return FALSE;
790             }
791 
792             if (state->return_type_tag == GI_TYPE_TAG_VOID) {
793                 /* The current return value is None. */
794                 Py_DECREF (state->return_value);
795             } else {
796                 /* Put the return value first. */
797                 g_assert (state->return_value != NULL);
798                 PyTuple_SET_ITEM (return_values, return_values_pos, state->return_value);
799                 return_values_pos += 1;
800             }
801 
802             state->return_value = return_values;
803         }
804 
805         for (i = 0; i < state->n_args; i++) {
806             GIDirection direction;
807             GITypeTag type_tag;
808             GITransfer transfer;
809 
810             if (state->args_is_auxiliary[i]) {
811                 /* Auxiliary arguments are handled at the same time as their relatives. */
812                 continue;
813             }
814 
815             direction = g_arg_info_get_direction (state->arg_infos[i]);
816             transfer = g_arg_info_get_ownership_transfer (state->arg_infos[i]);
817 
818             type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
819 
820             if ( (type_tag == GI_TYPE_TAG_ARRAY) &&
821                     (g_type_info_get_array_type (state->arg_type_infos[i]) == GI_ARRAY_TYPE_C) &&
822                     (direction != GI_DIRECTION_IN || transfer == GI_TRANSFER_NOTHING)) {
823                 /* Create a #GArray. */
824                 state->args[i]->v_pointer = _pygi_argument_to_array (state->args[i], state->args, state->arg_type_infos[i], state->is_method);
825             }
826 
827             if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT) {
828                 /* Convert the argument. */
829                 PyObject *obj;
830 
831                 /* If we created it, deallocate when it goes out of scope
832                  * otherwise it is unsafe to deallocate random structures
833                  * we are given
834                  */
835                 if (type_tag == GI_TYPE_TAG_INTERFACE) {
836                     GIBaseInfo *info;
837                     GIInfoType info_type;
838                     GType type;
839 
840                     info = g_type_info_get_interface (state->arg_type_infos[i]);
841                     g_assert (info != NULL);
842                     info_type = g_base_info_get_type (info);
843                     type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
844 
845                     if ( (info_type == GI_INFO_TYPE_STRUCT) &&
846                              !g_struct_info_is_foreign((GIStructInfo *) info) &&
847                              !g_type_is_a (type, G_TYPE_BOXED)) {
848                         if (g_arg_info_is_caller_allocates (state->arg_infos[i])) {
849                             transfer = GI_TRANSFER_EVERYTHING;
850                         } else if (transfer == GI_TRANSFER_EVERYTHING) {
851                             transfer = GI_TRANSFER_NOTHING;
852                             g_warning ("Out argument %ld in %s returns a struct "
853                                        "with a transfer mode of \"full\". "
854                                        "Transfer mode should be set to \"none\" for "
855                                        "struct type returns as there is no way to free "
856                                        "them safely.  Ignoring transfer mode "
857                                        "to prevent a potential invalid free. "
858                                        "This may cause a leak in your application.",
859                                        i, g_base_info_get_name ( (GIBaseInfo *) function_info) );
860                         }
861                     }
862                 }
863 
864                 obj = _pygi_argument_to_object (state->args[i], state->arg_type_infos[i], transfer);
865                 if (obj == NULL) {
866                     /* TODO: release arguments. */
867                     return FALSE;
868                 }
869 
870                 g_assert (return_values_pos < state->n_return_values);
871 
872                 if (state->n_return_values > 1) {
873                     PyTuple_SET_ITEM (state->return_value, return_values_pos, obj);
874                 } else {
875                     /* The current return value is None. */
876                     Py_DECREF (state->return_value);
877                     state->return_value = obj;
878                 }
879 
880                 return_values_pos += 1;
881             }
882 
883         }
884 
885         /* HACK: We rewrapped any C arrays above in a GArray so they are ok to
886          *       free as GArrays.  We will always leak C arrays if there is
887          *       an error before we reach this state as there is no easy way
888          *       to know which arrays were wrapped if there are more than one.
889          *       This will be removed with better array handling once merge
890          *       the invoke rewrite branch.
891          */
892         state->c_arrays_are_wrapped = TRUE;
893         g_assert (state->n_return_values <= 1 || return_values_pos == state->n_return_values);
894     }
895 
896     return TRUE;
897 }
898 
899 static void
_free_invocation_state(struct invocation_state * state)900 _free_invocation_state (struct invocation_state *state)
901 {
902     gsize i;
903     gsize backup_args_pos;
904 
905     if (state->return_type_info != NULL) {
906         g_base_info_unref ( (GIBaseInfo *) state->return_type_info);
907     }
908 
909     if (state->closure != NULL) {
910         if (state->closure->scope == GI_SCOPE_TYPE_CALL)
911             _pygi_invoke_closure_free (state->closure);
912     }
913 
914     /* release all arguments. */
915     backup_args_pos = 0;
916     for (i = 0; i < state->n_args; i++) {
917 
918         if (state->args_is_auxiliary[i]) {
919             /* Auxiliary arguments are not released. */
920             continue;
921         }
922 
923         if (state->arg_infos[i] != NULL
924             && state->arg_type_infos[i] != NULL) {
925             GIDirection direction;
926             GITypeTag type_tag;
927             GITransfer transfer;
928 
929             direction = g_arg_info_get_direction (state->arg_infos[i]);
930             transfer = g_arg_info_get_ownership_transfer (state->arg_infos[i]);
931 
932             /* Release the argument. */
933             if (direction == GI_DIRECTION_INOUT) {
934                 if (state->args != NULL) {
935                     _pygi_argument_release (&state->backup_args[backup_args_pos],
936                                             state->arg_type_infos[i],
937                                             transfer, GI_DIRECTION_IN);
938                 }
939                 backup_args_pos += 1;
940             }
941             if (state->args != NULL && state->args[i] != NULL) {
942                 type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
943 
944                 if (type_tag == GI_TYPE_TAG_ARRAY &&
945                         (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) &&
946                         (g_type_info_get_array_type (state->arg_type_infos[i]) == GI_ARRAY_TYPE_C) &&
947                         !state->c_arrays_are_wrapped) {
948                     /* HACK: Noop - we are in an inconsitant state due to
949                      *       complex array handler so leak any C arrays
950                      *       as we don't know if we can free them safely.
951                      *       This will be removed when we merge the
952                      *       invoke rewrite branch.
953                      */
954                 } else {
955                     _pygi_argument_release (state->args[i], state->arg_type_infos[i],
956                                             transfer, direction);
957                 }
958 
959                 if (type_tag == GI_TYPE_TAG_ARRAY
960                     && (direction != GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) {
961                     /* We created an *out* #GArray and it has not been released above, so free it. */
962                     state->args[i]->v_pointer = g_array_free (state->args[i]->v_pointer, FALSE);
963                 }
964             }
965 
966         }
967 
968         if (state->arg_type_infos[i] != NULL)
969             g_base_info_unref ( (GIBaseInfo *) state->arg_type_infos[i]);
970         if (state->arg_infos[i] != NULL)
971             g_base_info_unref ( (GIBaseInfo *) state->arg_infos[i]);
972     }
973     g_assert (backup_args_pos == state->n_backup_args);
974 
975     g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_infos);
976     g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_type_infos);
977     g_slice_free1 (sizeof (gboolean) * state->n_args, state->args_is_auxiliary);
978 
979     if (state->args != NULL) {
980         g_slice_free1 (sizeof (gpointer) * state->n_args, state->args);
981     }
982 
983     if (state->in_args != NULL) {
984         g_slice_free1 (sizeof (GIArgument) * state->n_in_args, state->in_args);
985     }
986 
987     if (state->out_args != NULL) {
988         g_slice_free1 (sizeof (GIArgument) * state->n_out_args, state->out_args);
989     }
990 
991     if (state->out_values != NULL) {
992         g_slice_free1 (sizeof (GIArgument) * state->n_out_args, state->out_values);
993     }
994 
995     if (state->backup_args != NULL) {
996         g_slice_free1 (sizeof (GIArgument) * state->n_backup_args, state->backup_args);
997     }
998 
999     if (PyErr_Occurred()) {
1000         Py_CLEAR (state->return_value);
1001     }
1002 }
1003 
1004 
1005 PyObject *
_wrap_g_callable_info_invoke(PyGIBaseInfo * self,PyObject * py_args,PyObject * kwargs)1006 _wrap_g_callable_info_invoke (PyGIBaseInfo *self, PyObject *py_args,
1007                               PyObject *kwargs)
1008 {
1009     struct invocation_state state = { 0, };
1010 
1011     if (!_initialize_invocation_state (&state, self->info, py_args, kwargs)) {
1012         _free_invocation_state (&state);
1013         return NULL;
1014     }
1015 
1016     if (!_prepare_invocation_state (&state, self->info, py_args)) {
1017         _free_invocation_state (&state);
1018         return NULL;
1019     }
1020 
1021     if (!_invoke_function (&state, self->info, py_args)) {
1022         _free_invocation_state (&state);
1023         return NULL;
1024     }
1025 
1026     if (!_process_invocation_state (&state, self->info, py_args)) {
1027         _free_invocation_state (&state);
1028         return NULL;
1029     }
1030 
1031     _free_invocation_state (&state);
1032     return state.return_value;
1033 }
1034 
1035