From 8e96029a32ef8be00ba8eee4306fc07722a94ef9 Mon Sep 17 00:00:00 2001 From: Cimbali Date: Mon, 1 Nov 2021 17:22:50 +0100 Subject: [PATCH] Create new API for libffi closures Deprecate the previous API as per discussion in !283. --- girffi.c | 75 ++++++++++++++++++++++++++++++++++++++++------- girffi.h | 21 +++++++++---- giversionmacros.h | 14 +++++++++ 3 files changed, 94 insertions(+), 16 deletions(-) diff --git a/girffi.c b/girffi.c index 127702039..851651321 100644 --- a/girffi.c +++ b/girffi.c @@ -353,7 +353,7 @@ typedef struct { } GIClosureWrapper; /** - * g_callable_info_prepare_closure: + * g_callable_info_create_closure: * @callable_info: a callable info from a typelib * @cif: a ffi_cif structure * @callback: the ffi callback @@ -362,13 +362,13 @@ typedef struct { * Prepares a callback for ffi invocation. * * Returns: the ffi_closure or NULL on error. The return value - * should be freed by calling g_callable_info_free_closure(). + * should be freed by calling g_callable_info_destroy_closure(). */ ffi_closure * -g_callable_info_prepare_closure (GICallableInfo *callable_info, - ffi_cif *cif, - GIFFIClosureCallback callback, - gpointer user_data) +g_callable_info_create_closure (GICallableInfo *callable_info, + ffi_cif *cif, + GIFFIClosureCallback callback, + gpointer user_data) { gpointer exec_ptr; int n_args; @@ -389,6 +389,7 @@ g_callable_info_prepare_closure (GICallableInfo *callable_info, closure->writable_self = closure; closure->native_address = exec_ptr; + atypes = g_callable_info_get_ffi_arg_types (callable_info, &n_args); status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, n_args, g_callable_info_get_ffi_return_type (callable_info), @@ -416,7 +417,7 @@ g_callable_info_prepare_closure (GICallableInfo *callable_info, * @callable_info: a callable info from a typelib * @closure: ffi closure * - * Gets callable code from ffi_closure prepared by g_callable_info_prepare_closure() + * Gets callable code from ffi_closure prepared by g_callable_info_create_closure() */ gpointer * g_callable_info_get_closure_native_address (GICallableInfo *callable_info, @@ -427,18 +428,70 @@ g_callable_info_get_closure_native_address (GICallableInfo *callable_info, } /** - * g_callable_info_free_closure: + * g_callable_info_destroy_closure: * @callable_info: a callable info from a typelib * @closure: ffi closure * - * Frees a ffi_closure returned from g_callable_info_prepare_closure() + * Frees a ffi_closure returned from g_callable_info_create_closure() */ void -g_callable_info_free_closure (GICallableInfo *callable_info, - ffi_closure *closure) +g_callable_info_destroy_closure (GICallableInfo *callable_info, + ffi_closure *closure) { GIClosureWrapper *wrapper = (GIClosureWrapper *)closure; g_free (wrapper->ffi_closure.cif->arg_types); ffi_closure_free (wrapper->writable_self); } + +/** + * g_callable_info_prepare_closure: + * @callable_info: a callable info from a typelib + * @cif: a ffi_cif structure + * @callback: the ffi callback + * @user_data: data to be passed into the callback + * + * Prepares a callback for ffi invocation. Deprecated + * + * Returns: the native address of the closre or NULL on error. The return value + * should be freed by calling g_callable_info_free_closure(). + */ +ffi_closure * +g_callable_info_prepare_closure (GICallableInfo *callable_info, + ffi_cif *cif, + GIFFIClosureCallback callback, + gpointer user_data) +{ + ffi_closure * closure; + + closure = g_callable_info_create_closure(callable_info, cif, callback, user_data); + if (!closure) + { + return NULL; + } + + g_warning ("g_callable_info_prepare_closure is deprecated, use g_callable_info_create_closure instead\n"); + + /* Return the native pointer which, on some systems and ffi versions without static exec trampolines, + * points to the same underlying memory as closure, but via an executable-non-writable mapping. + * Deprecated, and kept for backwards compatibility only. Risks segfaults on freeing the closure. + */ + return (ffi_closure *) g_callable_info_get_closure_native_address(callable_info, closure); +} + +/** + * g_callable_info_free_closure: + * @callable_info: a callable info from a typelib + * @closure: ffi closure + * + * Does nothing. (Leaks memory!) Use g_callable_info_destroy_closure() instead, + * in conjunction with g_callable_info_create_closure(). + * + * Should free a ffi_closure returned from g_callable_info_prepare_closure(), + * which may cause a segfault because the native address is returned instead + * of the closure address. + */ +void g_callable_info_free_closure (GICallableInfo *callable_info, ffi_closure *closure) +{ + g_warning ("g_callable_info_free_closure is deprecated and leaks memory\n"); +} diff --git a/girffi.h b/girffi.h index c6cb5e91b..2bbc97ac3 100644 --- a/girffi.h +++ b/girffi.h @@ -90,19 +90,30 @@ GI_AVAILABLE_IN_ALL void g_function_invoker_destroy (GIFunctionInvoker *invoker); -GI_AVAILABLE_IN_ALL +GI_DEPRECATED_IN_1_72_FOR(g_callable_info_create_closure) ffi_closure * g_callable_info_prepare_closure (GICallableInfo *callable_info, ffi_cif *cif, GIFFIClosureCallback callback, gpointer user_data); -GI_AVAILABLE_IN_1_70 +GI_DEPRECATED_IN_1_72_FOR(g_callable_info_destroy_closure) +void g_callable_info_free_closure (GICallableInfo *callable_info, + ffi_closure *closure); + + +GI_AVAILABLE_IN_1_72 +ffi_closure * g_callable_info_create_closure (GICallableInfo *callable_info, + ffi_cif *cif, + GIFFIClosureCallback callback, + gpointer user_data); + +GI_AVAILABLE_IN_1_72 gpointer * g_callable_info_get_closure_native_address (GICallableInfo *callable_info, ffi_closure *closure); -GI_AVAILABLE_IN_ALL -void g_callable_info_free_closure (GICallableInfo *callable_info, - ffi_closure *closure); +GI_AVAILABLE_IN_1_72 +void g_callable_info_destroy_closure (GICallableInfo *callable_info, + ffi_closure *closure); G_END_DECLS diff --git a/giversionmacros.h b/giversionmacros.h index 273af7253..d1b1733c0 100644 --- a/giversionmacros.h +++ b/giversionmacros.h @@ -171,4 +171,18 @@ # define GI_AVAILABLE_IN_1_70 _GI_EXTERN #endif +#if defined(GLIB_VERSION_2_72) && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_72 +# define GI_DEPRECATED_IN_1_72 GLIB_DEPRECATED +# define GI_DEPRECATED_IN_1_72_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define GI_DEPRECATED_IN_1_72 _GI_EXTERN +# define GI_DEPRECATED_IN_1_72_FOR(f) _GI_EXTERN +#endif + +#if defined(GLIB_VERSION_2_72) && GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_72 +# define GI_AVAILABLE_IN_1_72 GLIB_UNAVAILABLE(2, 72) +#else +# define GI_AVAILABLE_IN_1_72 _GI_EXTERN +#endif + #endif /* __GIVERSIONMACROS_H__ */