diff options
author | Evan Welsh <contact@evanwelsh.com> | 2022-03-06 14:36:10 -0800 |
---|---|---|
committer | Evan Welsh <contact@evanwelsh.com> | 2022-03-06 14:45:33 -0800 |
commit | bcf9feeb96678ec698d76c4f7cb1dbc465972ad5 (patch) | |
tree | b28d4233aaf7e86e90c6bf670c51ba4cf00b2de2 | |
parent | dce9f364632c9e2c80e79b988ff930e662b7afc4 (diff) | |
download | gjs-bcf9feeb96678ec698d76c4f7cb1dbc465972ad5.tar.gz |
gi: Use new GObject Introspection callable API
This avoids misusing the closure pointer by creating a clear
separation between the native closure pointer and the pointer
to the libffi closure.
Fixes #428
-rw-r--r-- | gi/arg-cache.cpp | 2 | ||||
-rw-r--r-- | gi/function.cpp | 39 | ||||
-rw-r--r-- | gi/function.h | 9 | ||||
-rw-r--r-- | gi/object.cpp | 5 |
4 files changed, 35 insertions, 20 deletions
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp index 83c4ad4d..177f246f 100644 --- a/gi/arg-cache.cpp +++ b/gi/arg-cache.cpp @@ -826,7 +826,7 @@ GJS_JSAPI_RETURN_CONVENTION bool CallbackIn::in(JSContext* cx, GjsFunctionCallState* state, GIArgument* arg, JS::HandleValue value) { GjsCallbackTrampoline* trampoline; - ffi_closure* closure; + void* closure; if (value.isNull() && m_nullable) { closure = nullptr; diff --git a/gi/function.cpp b/gi/function.cpp index 716acc8e..5c4fa4a2 100644 --- a/gi/function.cpp +++ b/gi/function.cpp @@ -640,8 +640,13 @@ GjsCallbackTrampoline::GjsCallbackTrampoline( } GjsCallbackTrampoline::~GjsCallbackTrampoline() { - if (m_info && m_closure) + if (m_info && m_closure) { +#if GI_CHECK_VERSION(1, 71, 0) + g_callable_info_destroy_closure(m_info, m_closure); +#else g_callable_info_free_closure(m_info, m_closure); +#endif + } } void GjsCallbackTrampoline::mark_forever() { @@ -652,6 +657,23 @@ void GjsCallbackTrampoline::prepare_shutdown() { s_forever_closure_list.clear(); } +ffi_closure* GjsCallbackTrampoline::create_closure() { + auto callback = [](ffi_cif*, void* result, void** ffi_args, void* data) { + auto** args = reinterpret_cast<GIArgument**>(ffi_args); + g_assert(data && "Trampoline data is not set"); + Gjs::Closure::Ptr trampoline(static_cast<GjsCallbackTrampoline*>(data), + GjsAutoTakeOwnership()); + + trampoline.as<GjsCallbackTrampoline>()->callback_closure(args, result); + }; + +#if GI_CHECK_VERSION(1, 71, 0) + return g_callable_info_create_closure(m_info, &m_cif, callback, this); +#else + return g_callable_info_prepare_closure(m_info, &m_cif, callback, this); +#endif +} + bool GjsCallbackTrampoline::initialize() { g_assert(is_valid()); g_assert(!m_closure); @@ -720,20 +742,7 @@ bool GjsCallbackTrampoline::initialize() { } } - m_closure = g_callable_info_prepare_closure( - m_info, &m_cif, - [](ffi_cif*, void* result, void** ffi_args, void* data) { - auto** args = reinterpret_cast<GIArgument**>(ffi_args); - g_assert(data && "Trampoline data is not set"); - Gjs::Closure::Ptr trampoline( - static_cast<GjsCallbackTrampoline*>(data), - GjsAutoTakeOwnership()); - - trampoline.as<GjsCallbackTrampoline>()->callback_closure(args, - result); - }, - this); - + m_closure = create_closure(); return true; } diff --git a/gi/function.h b/gi/function.h index a6e9b82d..799c1490 100644 --- a/gi/function.h +++ b/gi/function.h @@ -49,13 +49,20 @@ struct GjsCallbackTrampoline : public Gjs::Closure { ~GjsCallbackTrampoline(); - constexpr ffi_closure* closure() const { return m_closure; } + void* closure() const { +#if GI_CHECK_VERSION(1, 71, 0) + return g_callable_info_get_closure_native_address(m_info, m_closure); +#else + return m_closure; +#endif + } void mark_forever(); static void prepare_shutdown(); private: + ffi_closure* create_closure(); GJS_JSAPI_RETURN_CONVENTION bool initialize(); GjsCallbackTrampoline(JSContext* cx, JS::HandleFunction function, GICallableInfo* callable_info, GIScopeType scope, diff --git a/gi/object.cpp b/gi/object.cpp index a53f9e52..6c85631c 100644 --- a/gi/object.cpp +++ b/gi/object.cpp @@ -18,7 +18,6 @@ #include <utility> // for move #include <vector> -#include <ffi.h> #include <girepository.h> #include <glib-object.h> #include <glib.h> @@ -3004,7 +3003,7 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx, if (field_info) { gint offset; - gpointer method_ptr; + void* method_ptr; GjsCallbackTrampoline *trampoline; offset = g_field_info_get_offset(field_info); @@ -3032,7 +3031,7 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx, trampoline, nullptr, [](void*, GClosure* closure) { g_closure_unref(closure); }); - *reinterpret_cast<ffi_closure**>(method_ptr) = trampoline->closure(); + *reinterpret_cast<void**>(method_ptr) = trampoline->closure(); } return true; |