summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjellahlstedt@gmail.com>2023-03-27 15:20:04 +0200
committerKjell Ahlstedt <kjellahlstedt@gmail.com>2023-03-27 15:20:04 +0200
commitb7ad9b86d70003c065606c563578cc66dcd2ce0a (patch)
tree264e2c4723ba49647707a71b04c778f2e5b30124
parentd3874b1ec56d6db6b393e94daa1aded0f94d4b8b (diff)
downloadglibmm-b7ad9b86d70003c065606c563578cc66dcd2ce0a.tar.gz
Gio: Use callback functions with C linkage
* gio/giomm/socketsource.cc: Add extern "C". * gio/src/application.[ccg|hg]: Call Application_Class::open_callback() via a local function with C linkage. * gio/src/asyncinitable.[ccg|hg]: Call AsyncInitable_Class::init_async_vfunc_callback() and init_finish_vfunc_callback() via local functions with C linkage. * gio/src/dbusobjectmanagerclient.ccg: Use a local function with C linkage instead of Glib::destroy_notify_delete<SlotProxyType>. * gio/src/file.ccg: Add extern "C". * gio/src/liststore.ccg: Add a TODO comment. * gio/src/memoryinputstream.ccg: Add extern "C". * gio/src/settings.ccg: Add extern "C". * gio/src/socketcontrolmessage.[ccg|hg]: Call SocketControlMessage_Class::deserialize_async_vfunc_callback() via a local function with C linkage. Code that mixes up C linkage and C++ linkage has undefined behavior. Most compilers make no difference between C and C++ linkage, so it has not been an issue so far. Part of issue #1
-rw-r--r--gio/giomm/socketsource.cc11
-rw-r--r--gio/src/application.ccg27
-rw-r--r--gio/src/application.hg3
-rw-r--r--gio/src/asyncinitable.ccg29
-rw-r--r--gio/src/asyncinitable.hg8
-rw-r--r--gio/src/dbusobjectmanagerclient.ccg13
-rw-r--r--gio/src/file.ccg4
-rw-r--r--gio/src/liststore.ccg6
-rw-r--r--gio/src/memoryinputstream.ccg8
-rw-r--r--gio/src/settings.ccg12
-rw-r--r--gio/src/socketcontrolmessage.ccg17
-rw-r--r--gio/src/socketcontrolmessage.hg3
12 files changed, 116 insertions, 25 deletions
diff --git a/gio/giomm/socketsource.cc b/gio/giomm/socketsource.cc
index e46af5dd..e95f6946 100644
--- a/gio/giomm/socketsource.cc
+++ b/gio/giomm/socketsource.cc
@@ -22,8 +22,9 @@
namespace
{
-
-gboolean
+extern "C"
+{
+static gboolean
giomm_generic_socket_callback(sigc::slot_base* slot, GIOCondition condition)
{
g_return_val_if_fail(slot != nullptr, FALSE);
@@ -40,20 +41,20 @@ giomm_generic_socket_callback(sigc::slot_base* slot, GIOCondition condition)
return 0;
}
-gboolean
+static gboolean
giomm_signalsocket_callback(GSocket*, GIOCondition condition, void* user_data)
{
sigc::slot_base* const slot = Glib::Source::get_slot_from_connection_node(user_data);
return giomm_generic_socket_callback(slot, condition);
}
-gboolean
+static gboolean
giomm_socketsource_callback(GSocket*, GIOCondition condition, void* user_data)
{
sigc::slot_base* const slot = Glib::Source::get_slot_from_callback_data(user_data);
return giomm_generic_socket_callback(slot, condition);
}
-
+} // extern "C"
} // anonymous namespace
namespace Gio
diff --git a/gio/src/application.ccg b/gio/src/application.ccg
index d85ae8d7..e1a9f3f5 100644
--- a/gio/src/application.ccg
+++ b/gio/src/application.ccg
@@ -27,9 +27,25 @@ using Flags = Gio::Application::Flags;
namespace // anonymous
{
+// The function pointer, Application_signal_open_funcptr, is set in
+// Application_Class::class_init_function() (generated by gmmproc), making it
+// possible to indirectly call an Application_Class member function from
+// a function with C linkage.
+using Application_signal_open_functype = void (*) (GApplication* self, GFile** files, gint n_files, const gchar* hint);
+Application_signal_open_functype Application_signal_open_funcptr;
+
+extern "C"
+{
+// Shall be static. Non-static functions with C linkage get external linkage,
+// even if they are defined in an anonymous namespace.
+static void
+Application_signal_open_default_callback(GApplication* self, GFile** files, gint n_files, const gchar* hint)
+{
+ Application_signal_open_funcptr(self, files, n_files, hint);
+}
static void
-Application_signal_open_callback(
+Application_signal_open_connect_callback(
GApplication* self, GFile** files, gint n_files, const gchar* hint, void* data)
{
using SlotType = sigc::slot<void(const Gio::Application::type_vec_files&, const Glib::ustring&)>;
@@ -96,9 +112,10 @@ Application_signal_open_notify_callback(
return;
}
+} // extern "C"
static const Glib::SignalProxyInfo Application_signal_open_info = { "open",
- (GCallback)&Application_signal_open_callback,
+ (GCallback)&Application_signal_open_connect_callback,
(GCallback)&Application_signal_open_notify_callback };
// The add_main_option_entry*() methods that take a slot parameter are handled
@@ -190,7 +207,9 @@ OptionArgCallbackDataMap option_arg_callback_data;
// Accesses to option_arg_callback_data must be thread-safe.
std::mutex option_arg_callback_data_mutex;
-gboolean
+extern "C"
+{
+static gboolean
Application_option_arg_callback(
const gchar* option_name, const gchar* value, gpointer /* data */, GError** error)
{
@@ -256,7 +275,7 @@ Application_option_arg_callback(
}
return false;
}
-
+} // extern "C"
} // anonymous namespace
namespace Gio
diff --git a/gio/src/application.hg b/gio/src/application.hg
index cf59206e..7de44ee1 100644
--- a/gio/src/application.hg
+++ b/gio/src/application.hg
@@ -428,7 +428,8 @@ protected:
#m4begin
_PUSH(SECTION_PCC_CLASS_INIT_DEFAULT_SIGNAL_HANDLERS)
- klass->open = &open_callback;
+ klass->open = &Application_signal_open_default_callback;
+ Application_signal_open_funcptr = &open_callback;
_SECTION(SECTION_PH_DEFAULT_SIGNAL_HANDLERS)
static void open_callback(GApplication* self, GFile** files, gint n_files, const gchar* hint);
_POP()
diff --git a/gio/src/asyncinitable.ccg b/gio/src/asyncinitable.ccg
index 314c5b3f..38b5dd1c 100644
--- a/gio/src/asyncinitable.ccg
+++ b/gio/src/asyncinitable.ccg
@@ -20,6 +20,35 @@
#include <giomm/cancellable.h>
#include <giomm/slot_async.h>
+namespace // anonymous
+{
+using AsyncInitable_init_async_vfunc_functype = void (*) (GAsyncInitable* self,
+ int io_priority, GCancellable* cancellable, GAsyncReadyCallback callback,
+ gpointer user_data);
+using AsyncInitable_init_finish_vfunc_functype = gboolean (*) (GAsyncInitable* self,
+ GAsyncResult* res, GError** error);
+
+AsyncInitable_init_async_vfunc_functype AsyncInitable_init_async_vfunc_funcptr;
+AsyncInitable_init_finish_vfunc_functype AsyncInitable_init_finish_vfunc_funcptr;
+
+extern "C"
+{
+static void
+AsyncInitable_init_async_vfunc_c_callback(GAsyncInitable* self, int io_priority,
+ GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ AsyncInitable_init_async_vfunc_funcptr(self, io_priority, cancellable, callback, user_data);
+}
+
+static gboolean
+AsyncInitable_init_finish_vfunc_c_callback(GAsyncInitable* self,
+ GAsyncResult* res, GError** error)
+{
+ return AsyncInitable_init_finish_vfunc_funcptr(self, res, error);
+}
+} // extern "C"
+} // anonymous namespace
+
namespace Gio
{
diff --git a/gio/src/asyncinitable.hg b/gio/src/asyncinitable.hg
index 842ec45d..e833e83b 100644
--- a/gio/src/asyncinitable.hg
+++ b/gio/src/asyncinitable.hg
@@ -105,13 +105,15 @@ protected:
/** @throw Glib::Errror.
*/
- virtual bool init_finish_vfunc(const Glib::RefPtr<AsyncResult>& res);
+ virtual bool init_finish_vfunc(const Glib::RefPtr<AsyncResult>& res);
protected:
#m4begin
_PUSH(SECTION_PCC_CLASS_INIT_VFUNCS)
- klass->init_async = &init_async_vfunc_callback;
- klass->init_finish = &init_finish_vfunc_callback;
+ klass->init_async = &AsyncInitable_init_async_vfunc_c_callback;
+ klass->init_finish = &AsyncInitable_init_finish_vfunc_c_callback;
+ AsyncInitable_init_async_vfunc_funcptr = &init_async_vfunc_callback;
+ AsyncInitable_init_finish_vfunc_funcptr = &init_finish_vfunc_callback;
_SECTION(SECTION_PH_VFUNCS)
static void init_async_vfunc_callback(GAsyncInitable* self,
int io_priority, GCancellable* cancellable, GAsyncReadyCallback callback,
diff --git a/gio/src/dbusobjectmanagerclient.ccg b/gio/src/dbusobjectmanagerclient.ccg
index 76cc808e..5450ac09 100644
--- a/gio/src/dbusobjectmanagerclient.ccg
+++ b/gio/src/dbusobjectmanagerclient.ccg
@@ -18,7 +18,9 @@
namespace
{
-GType get_proxy_type_callback(GDBusObjectManagerClient* manager,
+extern "C"
+{
+static GType get_proxy_type_callback(GDBusObjectManagerClient* manager,
const gchar* object_path, const gchar* interface_name, gpointer user_data)
{
auto slot_proxy_type = static_cast<Gio::DBus::ObjectManagerClient::SlotProxyType*>(user_data);
@@ -35,6 +37,11 @@ GType get_proxy_type_callback(GDBusObjectManagerClient* manager,
return 0;
}
+static void proxy_type_callback_delete(void* data)
+{
+ delete static_cast<Gio::DBus::ObjectManagerClient::SlotProxyType*>(data);
+}
+} // extern "C"
} // anonymous namespace
namespace Gio
@@ -56,7 +63,7 @@ ObjectManagerClient::ObjectManagerClient(const Glib::RefPtr<Connection>& connect
"object-path", Glib::c_str_or_nullptr(object_path),
"get-proxy-type-func", slot_proxy_type ? get_proxy_type_callback : nullptr,
"get-proxy-type-user-data", slot_proxy_type ? new SlotProxyType(slot_proxy_type) : nullptr,
- "get-proxy-type-destroy-notify", slot_proxy_type ? Glib::destroy_notify_delete<SlotProxyType> : nullptr
+ "get-proxy-type-destroy-notify", slot_proxy_type ? proxy_type_callback_delete : nullptr
)
{
if (slot_async_ready)
@@ -88,7 +95,7 @@ ObjectManagerClient::ObjectManagerClient(BusType bus_type,
"object-path", Glib::c_str_or_nullptr(object_path),
"get-proxy-type-func", slot_proxy_type ? get_proxy_type_callback : nullptr,
"get-proxy-type-user-data", slot_proxy_type ? new SlotProxyType(slot_proxy_type) : nullptr,
- "get-proxy-type-destroy-notify", slot_proxy_type ? Glib::destroy_notify_delete<SlotProxyType> : nullptr
+ "get-proxy-type-destroy-notify", slot_proxy_type ? proxy_type_callback_delete : nullptr
)
{
if (slot_async_ready)
diff --git a/gio/src/file.ccg b/gio/src/file.ccg
index 8e8204a9..484bad52 100644
--- a/gio/src/file.ccg
+++ b/gio/src/file.ccg
@@ -28,6 +28,8 @@ using CopySlots = std::pair<Gio::File::SlotFileProgress*, Gio::SlotAsyncReady*>;
using MeasureSlots = std::pair<Gio::File::SlotFileMeasureProgress*, Gio::SlotAsyncReady*>;
using LoadPartialSlots = std::pair<Gio::File::SlotReadMore*, Gio::SlotAsyncReady*>;
+extern "C"
+{
static void
SignalProxy_file_progress_callback(
goffset current_num_bytes, goffset total_num_bytes, gpointer data)
@@ -162,7 +164,7 @@ SignalProxy_file_measure_progress_callback(
Glib::exception_handlers_invoke();
}
}
-
+} // extern "C"
} // anonymous namespace
namespace Gio
diff --git a/gio/src/liststore.ccg b/gio/src/liststore.ccg
index 9c95e7ef..dd5580f3 100644
--- a/gio/src/liststore.ccg
+++ b/gio/src/liststore.ccg
@@ -21,6 +21,9 @@ namespace
{
extern "C"
{
+// Non-static functions with C linkage get external linkage, even if they are
+// defined in an anonymous namespace.
+//TODO: Declare 'static' when we can break ABI.
int ListStoreBase_CompareDataFunc(gconstpointer a, gconstpointer b, gpointer user_data)
{
auto slot = static_cast<Gio::ListStoreBase::SlotCompare*>(user_data);
@@ -33,6 +36,7 @@ int ListStoreBase_CompareDataFunc(gconstpointer a, gconstpointer b, gpointer use
return (*slot)(item_a, item_b);
}
+//TODO: Declare 'static' when we can break ABI.
// gboolean is int
gboolean ListStoreBase_EqualFuncFull(gconstpointer a, gconstpointer b, gpointer user_data)
{
@@ -45,7 +49,7 @@ gboolean ListStoreBase_EqualFuncFull(gconstpointer a, gconstpointer b, gpointer
return (*slot)(item_a, item_b);
}
-}
+} // extern "C"
} // anonymous namespace
namespace Gio
diff --git a/gio/src/memoryinputstream.ccg b/gio/src/memoryinputstream.ccg
index 920e6166..ce620f41 100644
--- a/gio/src/memoryinputstream.ccg
+++ b/gio/src/memoryinputstream.ccg
@@ -39,7 +39,11 @@ private:
void* m_data;
};
-void
+extern "C"
+{
+// Shall be static. Non-static functions with C linkage get external linkage,
+// even if they are defined in an anonymous namespace.
+static void
destroy_data_callback(void* user_data)
{
auto slot_with_data = static_cast<SlotWithData*>(user_data);
@@ -56,7 +60,7 @@ destroy_data_callback(void* user_data)
delete slot_with_data;
}
-
+} // extern "C"
} // anonymous namespace
namespace Gio
diff --git a/gio/src/settings.ccg b/gio/src/settings.ccg
index 7343bb64..1651c0d5 100644
--- a/gio/src/settings.ccg
+++ b/gio/src/settings.ccg
@@ -33,7 +33,11 @@ struct SettingsMapSlots
Gio::Settings::SlotSetMapping from_property_to_setting;
};
-gboolean
+extern "C"
+{
+// Shall be static. Non-static functions with C linkage get external linkage,
+// even if they are defined in an anonymous namespace.
+static gboolean
Settings_get_mapping_callback(
GValue* to_value, GVariant* from_variant, gpointer user_data)
{
@@ -52,7 +56,7 @@ Settings_get_mapping_callback(
return result;
}
-GVariant*
+static GVariant*
Settings_set_mapping_callback(
const GValue* from_value, const GVariantType* expected_type, gpointer user_data)
{
@@ -71,12 +75,12 @@ Settings_set_mapping_callback(
return result;
}
-void
+static void
Settings_map_callback_destroy(gpointer user_data)
{
delete static_cast<SettingsMapSlots*>(user_data);
}
-
+} // extern "C"
} // anonymous namespace
namespace Gio
diff --git a/gio/src/socketcontrolmessage.ccg b/gio/src/socketcontrolmessage.ccg
index ff98610c..ba0924e3 100644
--- a/gio/src/socketcontrolmessage.ccg
+++ b/gio/src/socketcontrolmessage.ccg
@@ -17,6 +17,23 @@
#include <gio/gio.h>
#include <glibmm/exceptionhandler.h>
+namespace // anonymous
+{
+using SocketControlMessage_deserialize_vfunc_functype = GSocketControlMessage* (*)
+ (int level, int type, gsize size, gpointer data);
+
+SocketControlMessage_deserialize_vfunc_functype SocketControlMessage_deserialize_vfunc_funcptr;
+
+extern "C"
+{
+static GSocketControlMessage*
+SocketControlMessage_deserialize_vfunc_c_callback(int level, int type, gsize size, gpointer data)
+{
+ return SocketControlMessage_deserialize_vfunc_funcptr(level, type, size, data);
+}
+} // extern "C"
+} // anonymous namespace
+
namespace Gio
{
// static
diff --git a/gio/src/socketcontrolmessage.hg b/gio/src/socketcontrolmessage.hg
index 3048d8d7..0a7005bf 100644
--- a/gio/src/socketcontrolmessage.hg
+++ b/gio/src/socketcontrolmessage.hg
@@ -73,7 +73,8 @@ protected:
// https://gitlab.gnome.org/GNOME/glibmm/issues/52
#m4begin
_PUSH(SECTION_PCC_CLASS_INIT_VFUNCS)
- klass->deserialize = &deserialize_vfunc_callback;
+ klass->deserialize = &SocketControlMessage_deserialize_vfunc_c_callback;
+ SocketControlMessage_deserialize_vfunc_funcptr = &deserialize_vfunc_callback;
_SECTION(SECTION_PH_VFUNCS)
static GSocketControlMessage* deserialize_vfunc_callback(
int level, int type, gsize size, gpointer data);