summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Welsh <contact@evanwelsh.com>2022-03-06 14:36:10 -0800
committerEvan Welsh <contact@evanwelsh.com>2022-03-06 14:45:33 -0800
commitbcf9feeb96678ec698d76c4f7cb1dbc465972ad5 (patch)
treeb28d4233aaf7e86e90c6bf670c51ba4cf00b2de2
parentdce9f364632c9e2c80e79b988ff930e662b7afc4 (diff)
downloadgjs-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.cpp2
-rw-r--r--gi/function.cpp39
-rw-r--r--gi/function.h9
-rw-r--r--gi/object.cpp5
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;