PyObject * pygi_invoke_c_callable (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *py_args, PyObject *py_kwargs) { PyGICallableCache *cache = (PyGICallableCache *) function_cache; GIFFIReturnValue ffi_return_value = {0}; PyObject *ret = NULL; if (!_invoke_state_init_from_cache (state, function_cache, py_args, py_kwargs)) goto err; if (!_invoke_marshal_in_args (state, function_cache)) goto err; Py_BEGIN_ALLOW_THREADS; ffi_call (&function_cache->invoker.cif, state->function_ptr, (void *) &ffi_return_value, (void **) state->ffi_args); Py_END_ALLOW_THREADS; /* If the callable throws, the address of state->error will be bound into * the state->args as the last value. When the callee sets an error using * the state->args passed, it will have the side effect of setting * state->error allowing for easy checking here. */ if (state->error != NULL) { if (pygi_error_check (&state->error)) { /* even though we errored out, the call itself was successful, so we assume the call processed all of the parameters */ pygi_marshal_cleanup_args_from_py_marshal_success (state, cache); goto err; } } if (cache->return_cache) { gi_type_info_extract_ffi_return_value (cache->return_cache->type_info, &ffi_return_value, &state->return_arg); } ret = _invoke_marshal_out_args (state, function_cache); pygi_marshal_cleanup_args_from_py_marshal_success (state, cache); if (ret != NULL) pygi_marshal_cleanup_args_to_py_marshal_success (state, cache); err: _invoke_state_clear (state, function_cache); return ret; }
void _pygi_closure_handle (ffi_cif *cif, void *result, void **args, void *data) { PyGILState_STATE py_state; PyGICClosure *closure = data; PyObject *retval; gboolean success; PyGIInvokeState state = { 0, }; /* Ignore closures when Python is not initialized. This can happen in cases * where calling Python implemented vfuncs can happen at shutdown time. * See: https://bugzilla.gnome.org/show_bug.cgi?id=722562 */ if (!Py_IsInitialized()) { return; } /* Lock the GIL as we are coming into this code without the lock and we may be executing python code */ py_state = PyGILState_Ensure (); if (closure->cache == NULL) { closure->cache = pygi_closure_cache_new ((GICallableInfo *) closure->info); if (closure->cache == NULL) goto end; } state.user_data = closure->user_data; _invoke_state_init_from_cache (&state, closure->cache, args); if (!_pygi_closure_convert_arguments (&state, closure->cache)) { _pygi_closure_clear_retvals (&state, closure->cache, result); goto end; } retval = PyObject_CallObject ( (PyObject *) closure->function, state.py_in_args); if (retval == NULL) { _pygi_closure_clear_retvals (&state, closure->cache, result); goto end; } pygi_marshal_cleanup_args_to_py_marshal_success (&state, closure->cache); success = _pygi_closure_set_out_arguments (&state, closure->cache, retval, result); if (!success) { pygi_marshal_cleanup_args_from_py_marshal_success (&state, closure->cache); _pygi_closure_clear_retvals (&state, closure->cache, result); } Py_DECREF (retval); end: if (PyErr_Occurred ()) PyErr_Print (); /* Now that the closure has finished we can make a decision about how to free it. Scope call gets free'd at the end of wrap_g_function_info_invoke. Scope notified will be freed when the notify is called. Scope async closures free only their python data now and the closure later during the next creation of a closure. This minimizes potential ref leaks at least in regards to the python objects. (you can't free the closure you are currently using!) */ switch (closure->scope) { case GI_SCOPE_TYPE_CALL: case GI_SCOPE_TYPE_NOTIFIED: break; case GI_SCOPE_TYPE_ASYNC: /* Append this PyGICClosure to a list of closure that we will free after we're done with this function invokation */ _pygi_invoke_closure_clear_py_data(closure); async_free_list = g_slist_prepend (async_free_list, closure); break; default: g_error ("Invalid scope reached inside %s. Possibly a bad annotation?", g_base_info_get_name (closure->info)); } _invoke_state_clear (&state); PyGILState_Release (py_state); }