1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
5 * Copyright (C) 2011 John (J5) Palimier <johnp@redhat.com>
7 * pygi-invoke.c: main invocation function
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
26 #include "pygi-invoke.h"
27 #include "pygi-marshal-cleanup.h"
29 static inline gboolean
30 _invoke_callable (PyGIInvokeState *state,
31 PyGICallableCache *cache,
32 GICallableInfo *callable_info,
33 GCallback function_ptr)
40 Py_BEGIN_ALLOW_THREADS;
42 /* FIXME: use this for now but we can streamline the calls */
43 if (cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
44 retval = g_vfunc_info_invoke ( callable_info,
45 state->implementor_gtype,
47 cache->n_from_py_args,
52 else if (g_base_info_get_type (callable_info) == GI_INFO_TYPE_CALLBACK)
53 retval = g_callable_info_invoke (callable_info,
56 cache->n_from_py_args,
64 retval = g_function_info_invoke ( callable_info,
66 cache->n_from_py_args,
74 g_assert (error != NULL);
75 pyglib_error_check (&error);
77 /* It is unclear if the error occured before or after the C
78 * function was invoked so for now assume success
79 * We eventually should marshal directly to FFI so we no longer
80 * have to use the reference implementation
82 pygi_marshal_cleanup_args_from_py_marshal_success (state, cache);
87 if (state->error != NULL) {
88 if (pyglib_error_check (&(state->error))) {
89 /* even though we errored out, the call itself was successful,
90 so we assume the call processed all of the parameters */
91 pygi_marshal_cleanup_args_from_py_marshal_success (state, cache);
100 _check_for_unexpected_kwargs (const gchar *function_name,
101 GHashTable *arg_name_hash,
104 PyObject *dict_key, *dict_value;
105 Py_ssize_t dict_iter_pos = 0;
107 while (PyDict_Next (py_kwargs, &dict_iter_pos, &dict_key, &dict_value)) {
110 #if PY_VERSION_HEX < 0x03000000
111 if (PyString_Check (dict_key)) {
112 Py_INCREF (dict_key);
117 key = PyUnicode_AsUTF8String (dict_key);
123 if (g_hash_table_lookup (arg_name_hash, PyBytes_AsString(key)) == NULL) {
124 PyErr_Format (PyExc_TypeError,
125 "%.200s() got an unexpected keyword argument '%.400s'",
127 PyBytes_AsString (key));
138 * _py_args_combine_and_check_length:
139 * @cache: PyGICallableCache
140 * @py_args: the tuple of positional arguments.
141 * @py_kwargs: the dict of keyword arguments to be merged with py_args.
143 * Returns: New value reference to the combined py_args and py_kwargs.
146 _py_args_combine_and_check_length (PyGICallableCache *cache,
150 PyObject *combined_py_args = NULL;
151 Py_ssize_t n_py_args, n_py_kwargs, i;
152 guint n_expected_args;
154 const gchar *function_name = cache->name;
156 n_py_args = PyTuple_GET_SIZE (py_args);
157 if (py_kwargs == NULL)
160 n_py_kwargs = PyDict_Size (py_kwargs);
162 /* Fast path, we already have the exact number of args and not kwargs. */
163 n_expected_args = g_slist_length (cache->arg_name_list);
164 if (n_py_kwargs == 0 && n_py_args == n_expected_args) {
169 if (n_expected_args < n_py_args) {
170 PyErr_Format (PyExc_TypeError,
171 "%.200s() takes exactly %d %sargument%s (%zd given)",
174 n_py_kwargs > 0 ? "non-keyword " : "",
175 n_expected_args == 1 ? "" : "s",
180 if (n_py_kwargs > 0 && !_check_for_unexpected_kwargs (function_name,
181 cache->arg_name_hash,
186 /* will hold arguments from both py_args and py_kwargs
187 * when they are combined into a single tuple */
188 combined_py_args = PyTuple_New (n_expected_args);
190 for (i = 0; i < n_py_args; i++) {
191 PyObject *item = PyTuple_GET_ITEM (py_args, i);
193 PyTuple_SET_ITEM (combined_py_args, i, item);
196 for (i = 0, l = cache->arg_name_list; i < n_expected_args && l; i++, l = l->next) {
197 PyObject *py_arg_item, *kw_arg_item = NULL;
198 const gchar *arg_name = l->data;
200 if (n_py_kwargs > 0 && arg_name != NULL) {
201 /* NULL means this argument has no keyword name */
202 /* ex. the first argument to a method or constructor */
203 kw_arg_item = PyDict_GetItemString (py_kwargs, arg_name);
205 py_arg_item = PyTuple_GET_ITEM (combined_py_args, i);
207 if (kw_arg_item != NULL && py_arg_item == NULL) {
208 Py_INCREF (kw_arg_item);
209 PyTuple_SET_ITEM (combined_py_args, i, kw_arg_item);
211 } else if (kw_arg_item == NULL && py_arg_item == NULL) {
212 PyErr_Format (PyExc_TypeError,
213 "%.200s() takes exactly %d %sargument%s (%zd given)",
216 n_py_kwargs > 0 ? "non-keyword " : "",
217 n_expected_args == 1 ? "" : "s",
220 Py_DECREF (combined_py_args);
223 } else if (kw_arg_item != NULL && py_arg_item != NULL) {
224 PyErr_Format (PyExc_TypeError,
225 "%.200s() got multiple values for keyword argument '%.200s'",
229 Py_DECREF (combined_py_args);
234 return combined_py_args;
237 static inline gboolean
238 _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
239 PyGICallableCache *cache,
243 PyObject *combined_args = NULL;
244 state->implementor_gtype = 0;
246 /* TODO: We don't use the class parameter sent in by the structure
247 * so we remove it from the py_args tuple but we can keep it
248 * around if we want to call actual gobject constructors
249 * in the future instead of calling g_object_new
251 if (cache->function_type == PYGI_FUNCTION_TYPE_CONSTRUCTOR) {
252 PyObject *constructor_class;
253 constructor_class = PyTuple_GetItem (py_args, 0);
255 if (constructor_class == NULL) {
257 PyErr_Format (PyExc_TypeError,
258 "Constructors require the class to be passed in as an argument, "
259 "No arguments passed to the %s constructor.",
264 } else if (cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
266 py_gtype = PyTuple_GetItem (py_args, 0);
267 if (py_gtype == NULL) {
268 PyErr_SetString (PyExc_TypeError,
269 "need the GType of the implementor class");
273 state->implementor_gtype = pyg_type_from_object (py_gtype);
275 if (state->implementor_gtype == 0)
279 if (cache->function_type == PYGI_FUNCTION_TYPE_CONSTRUCTOR ||
280 cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
282 /* we could optimize this by using offsets instead of modifying the tuple but it makes the
283 * code more error prone and confusing so don't do that unless profiling shows
286 combined_args = PyTuple_GetSlice (py_args, 1, PyTuple_Size (py_args));
288 combined_args = py_args;
289 Py_INCREF (combined_args);
292 state->py_in_args = _py_args_combine_and_check_length (cache,
295 Py_DECREF (combined_args);
297 if (state->py_in_args == NULL) {
300 state->n_py_in_args = PyTuple_Size (state->py_in_args);
302 state->args = g_slice_alloc0 (cache->n_args * sizeof (GIArgument *));
303 if (state->args == NULL && cache->n_args != 0) {
308 state->args_data = g_slice_alloc0 (cache->n_args * sizeof (gpointer));
309 if (state->args_data == NULL && cache->n_args != 0) {
314 state->in_args = g_slice_alloc0 (cache->n_from_py_args * sizeof(GIArgument));
315 if (state->in_args == NULL && cache->n_from_py_args != 0) {
320 state->out_values = g_slice_alloc0 (cache->n_to_py_args * sizeof(GIArgument));
321 if (state->out_values == NULL && cache->n_to_py_args != 0) {
326 state->out_args = g_slice_alloc0 (cache->n_to_py_args * sizeof(GIArgument));
327 if (state->out_args == NULL && cache->n_to_py_args != 0) {
338 _invoke_state_clear (PyGIInvokeState *state, PyGICallableCache *cache)
340 g_slice_free1 (cache->n_args * sizeof(GIArgument *), state->args);
341 g_slice_free1 (cache->n_args * sizeof(gpointer), state->args_data);
342 g_slice_free1 (cache->n_from_py_args * sizeof(GIArgument), state->in_args);
343 g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_args);
344 g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_values);
346 Py_XDECREF (state->py_in_args);
349 static gboolean _caller_alloc (PyGIInvokeState *state,
350 PyGIArgCache *arg_cache,
354 if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
355 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
357 state->out_args[out_count].v_pointer = NULL;
358 state->args[arg_count] = &state->out_args[out_count];
359 if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
360 state->args[arg_count]->v_pointer =
361 _pygi_boxed_alloc (iface_cache->interface_info, NULL);
362 } else if (iface_cache->g_type == G_TYPE_VALUE) {
363 state->args[arg_count]->v_pointer = g_slice_new0 (GValue);
364 } else if (iface_cache->is_foreign) {
365 PyObject *foreign_struct =
366 pygi_struct_foreign_convert_from_g_argument (
367 iface_cache->interface_info,
370 pygi_struct_foreign_convert_to_g_argument (foreign_struct,
371 iface_cache->interface_info,
372 GI_TRANSFER_EVERYTHING,
373 state->args[arg_count]);
375 gssize size = g_struct_info_get_size(
376 (GIStructInfo *)iface_cache->interface_info);
377 state->args[arg_count]->v_pointer = g_malloc0 (size);
379 } else if (arg_cache->type_tag == GI_TYPE_TAG_ARRAY) {
380 PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
382 state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, seq_cache->item_size);
383 state->args[arg_count] = &state->out_args[out_count];
388 if (state->args[arg_count]->v_pointer == NULL)
395 static inline gboolean
396 _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
398 gssize i, in_count, out_count;
402 if (state->n_py_in_args > cache->n_py_args) {
403 PyErr_Format (PyExc_TypeError,
404 "%s() takes exactly %zd argument(s) (%zd given)",
407 state->n_py_in_args);
411 for (i = 0; i < cache->n_args; i++) {
413 PyGIArgCache *arg_cache = cache->args_cache[i];
414 PyObject *py_arg = NULL;
416 switch (arg_cache->direction) {
417 case PYGI_DIRECTION_FROM_PYTHON:
418 state->args[i] = &(state->in_args[in_count]);
421 if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CLOSURE) {
422 state->args[i]->v_pointer = state->user_data;
424 } else if (arg_cache->meta_type != PYGI_META_ARG_TYPE_PARENT)
427 if (arg_cache->py_arg_index >= state->n_py_in_args) {
428 PyErr_Format (PyExc_TypeError,
429 "%s() takes exactly %zd argument(s) (%zd given)",
432 state->n_py_in_args);
434 /* clean up all of the args we have already marshalled,
435 * since invoke will not be called
437 pygi_marshal_cleanup_args_from_py_parameter_fail (state,
444 PyTuple_GET_ITEM (state->py_in_args,
445 arg_cache->py_arg_index);
448 case PYGI_DIRECTION_BIDIRECTIONAL:
449 /* this will be filled in if it is an child value */
450 if (state->in_args[in_count].v_pointer != NULL)
451 state->out_values[out_count] = state->in_args[in_count];
453 state->in_args[in_count].v_pointer = &state->out_values[out_count];
456 if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD) {
457 if (arg_cache->py_arg_index >= state->n_py_in_args) {
458 PyErr_Format (PyExc_TypeError,
459 "%s() takes exactly %zd argument(s) (%zd given)",
462 state->n_py_in_args);
463 pygi_marshal_cleanup_args_from_py_parameter_fail (state,
470 PyTuple_GET_ITEM (state->py_in_args,
471 arg_cache->py_arg_index);
473 case PYGI_DIRECTION_TO_PYTHON:
474 if (arg_cache->is_caller_allocates) {
475 if (!_caller_alloc (state, arg_cache, i, out_count)) {
476 PyErr_Format (PyExc_TypeError,
477 "Could not caller allocate argument %zd of callable %s",
479 pygi_marshal_cleanup_args_from_py_parameter_fail (state,
485 state->out_args[out_count].v_pointer = &state->out_values[out_count];
486 state->args[i] = &state->out_values[out_count];
492 c_arg = state->args[i];
493 if (arg_cache->from_py_marshaller != NULL) {
495 if (!arg_cache->allow_none && py_arg == Py_None) {
496 PyErr_Format (PyExc_TypeError,
497 "Argument %zd does not allow None as a value",
500 pygi_marshal_cleanup_args_from_py_parameter_fail (state,
505 success = arg_cache->from_py_marshaller (state,
511 pygi_marshal_cleanup_args_from_py_parameter_fail (state,
524 static inline PyObject *
525 _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
527 PyObject *py_out = NULL;
528 PyObject *py_return = NULL;
529 gssize total_out_args = cache->n_to_py_args;
530 gboolean has_return = FALSE;
532 if (cache->return_cache) {
533 if (!cache->return_cache->is_skipped) {
534 if (cache->function_type == PYGI_FUNCTION_TYPE_CONSTRUCTOR) {
535 if (state->return_arg.v_pointer == NULL) {
536 PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
537 pygi_marshal_cleanup_args_return_fail (state,
543 py_return = cache->return_cache->to_py_marshaller ( state,
547 if (py_return == NULL) {
548 pygi_marshal_cleanup_args_return_fail (state,
554 if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) {
559 if (cache->return_cache->transfer == GI_TRANSFER_EVERYTHING) {
560 PyGIMarshalCleanupFunc to_py_cleanup =
561 cache->return_cache->to_py_cleanup;
563 if (to_py_cleanup != NULL)
564 to_py_cleanup ( state,
572 total_out_args -= cache->n_to_py_child_args;
574 if (cache->n_to_py_args - cache->n_to_py_child_args == 0) {
575 if (cache->return_cache->is_skipped && state->error == NULL) {
576 /* we skip the return value and have no (out) arguments to return,
577 * so py_return should be NULL. But we must not return NULL,
578 * otherwise Python will expect an exception.
580 g_assert (py_return == NULL);
586 } else if (total_out_args == 1) {
587 /* if we get here there is one out arg an no return */
588 PyGIArgCache *arg_cache = (PyGIArgCache *)cache->to_py_args->data;
589 py_out = arg_cache->to_py_marshaller (state,
592 state->args[arg_cache->c_arg_index]);
593 if (py_out == NULL) {
594 pygi_marshal_cleanup_args_to_py_parameter_fail (state,
601 gssize py_arg_index = 0;
602 GSList *cache_item = cache->to_py_args;
604 py_out = PyTuple_New (total_out_args);
606 PyTuple_SET_ITEM (py_out, py_arg_index, py_return);
610 for(; py_arg_index < total_out_args; py_arg_index++) {
611 PyGIArgCache *arg_cache = (PyGIArgCache *)cache_item->data;
612 PyObject *py_obj = arg_cache->to_py_marshaller (state,
615 state->args[arg_cache->c_arg_index]);
617 if (py_obj == NULL) {
621 pygi_marshal_cleanup_args_to_py_parameter_fail (state,
628 PyTuple_SET_ITEM (py_out, py_arg_index, py_obj);
629 cache_item = cache_item->next;
636 pygi_callable_info_invoke (GIBaseInfo *info, PyObject *py_args,
637 PyObject *kwargs, PyGICallableCache *cache,
638 GCallback function_ptr, gpointer user_data)
640 PyGIInvokeState state = { 0, };
641 PyObject *ret = NULL;
643 if (!_invoke_state_init_from_callable_cache (&state, cache, py_args, kwargs))
646 if (cache->function_type == PYGI_FUNCTION_TYPE_CCALLBACK)
647 state.user_data = user_data;
649 if (!_invoke_marshal_in_args (&state, cache))
652 if (!_invoke_callable (&state, cache, info, function_ptr))
655 pygi_marshal_cleanup_args_from_py_marshal_success (&state, cache);
657 ret = _invoke_marshal_out_args (&state, cache);
659 pygi_marshal_cleanup_args_to_py_marshal_success (&state, cache);
661 _invoke_state_clear (&state, cache);
666 _wrap_g_callable_info_invoke (PyGIBaseInfo *self, PyObject *py_args,
669 if (self->cache == NULL) {
670 self->cache = _pygi_callable_cache_new (self->info, FALSE);
671 if (self->cache == NULL)
675 return pygi_callable_info_invoke (self->info, py_args, kwargs, self->cache, NULL, NULL);