summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjellahlstedt@gmail.com>2023-03-31 19:00:02 +0200
committerKjell Ahlstedt <kjellahlstedt@gmail.com>2023-03-31 19:00:02 +0200
commit07fbd1f0e0a68fb3b130fe9d0b0f5f338346746a (patch)
tree4d3182fa5e2e9c99b6fd31519f0c6594ef291041
parent7ff8b74a47059edbba7a9f9424fa0022943bc6ec (diff)
downloadglibmm-07fbd1f0e0a68fb3b130fe9d0b0f5f338346746a.tar.gz
Glib: value_custom: Use callback functions with C linkage
* glib/glibmm/value_custom.[cc|h]: Add custom_boxed_type_cpp_register(). * tests/glibmm_value/main.cc: Add test of copying custom Value. Part of issue #1
-rw-r--r--glib/glibmm/value_custom.cc55
-rw-r--r--glib/glibmm/value_custom.h15
-rw-r--r--tests/glibmm_value/main.cc7
3 files changed, 73 insertions, 4 deletions
diff --git a/glib/glibmm/value_custom.cc b/glib/glibmm/value_custom.cc
index 15260704..0deac7b3 100644
--- a/glib/glibmm/value_custom.cc
+++ b/glib/glibmm/value_custom.cc
@@ -17,16 +17,49 @@
#include <glibmm/value.h>
#include <glibmm/utility.h>
#include <glib.h>
+#include <map>
namespace
{
+std::map<GType, Glib::ValueInitCppFuncType> custom_init_funcmap;
+std::map<GType, Glib::ValueFreeCppFuncType> custom_free_funcmap;
+std::map<GType, Glib::ValueCopyCppFuncType> custom_copy_funcmap;
+
+extern "C"
+{
+static void Value_custom_init_func(GValue* value)
+{
+ Glib::ValueInitCppFuncType init_func = custom_init_funcmap[G_VALUE_TYPE(value)];
+ if (init_func)
+ init_func(value);
+ else
+ g_critical("Value_custom_init_func(): No init_func for GValue %s\n", G_VALUE_TYPE_NAME(value));
+}
+static void Value_custom_free_func(GValue* value)
+{
+ Glib::ValueFreeCppFuncType free_func = custom_free_funcmap[G_VALUE_TYPE(value)];
+ if (free_func)
+ free_func(value);
+ else
+ g_critical("Value_custom_free_func(): No free_func for GValue %s\n", G_VALUE_TYPE_NAME(value));
+}
+static void Value_custom_copy_func(const GValue* src_value, GValue* dest_value)
+{
+ Glib::ValueCopyCppFuncType copy_func = custom_copy_funcmap[G_VALUE_TYPE(src_value)];
+ if (copy_func)
+ copy_func(src_value, dest_value);
+ else
+ g_critical("Value_custom_copy_func(): No copy_func for GValue %s\n", G_VALUE_TYPE_NAME(src_value));
+}
+} // extern "C"
static void
warn_already_registered(const char* location, const std::string& full_name)
{
g_warning("file %s: (%s): The type name `%s' has been registered already.\n"
- "This is not supposed to happen -- please send a mail with detailed "
- "information about your platform to gtkmm-list@gnome.org. Thanks.\n",
+ "This is not supposed to happen -- please create an issue with "
+ "detailed information about your platform\n"
+ "at https://gitlab.gnome.org/GNOME/glibmm/-/issues. Thanks.\n",
__FILE__, location, full_name.c_str());
}
@@ -36,6 +69,22 @@ namespace Glib
{
GType
+custom_boxed_type_cpp_register(const char* type_name,
+ ValueInitCppFuncType init_func, ValueFreeCppFuncType free_func,
+ ValueCopyCppFuncType copy_func)
+{
+ const GType custom_gtype = custom_boxed_type_register(type_name,
+ &Value_custom_init_func, &Value_custom_free_func, &Value_custom_copy_func);
+ custom_init_funcmap[custom_gtype] = init_func;
+ custom_free_funcmap[custom_gtype] = free_func;
+ custom_copy_funcmap[custom_gtype] = copy_func;
+ return custom_gtype;
+}
+
+//TODO: When we can break ABI, move the contents of custom_boxed_type_register()
+// (with small modifications) to custom_boxed_type_cpp_register() and
+// remove custom_boxed_type_register().
+GType
custom_boxed_type_register(
const char* type_name, ValueInitFunc init_func, ValueFreeFunc free_func, ValueCopyFunc copy_func)
{
@@ -61,6 +110,8 @@ custom_boxed_type_register(
// destroy, and copy arbitrary objects of the C++ type.
const GTypeValueTable value_table = {
+ //TODO: When moved to custom_boxed_type_cpp_register():
+ // &Value_custom_init_func, &Value_custom_free_func, &Value_custom_copy_func,
init_func, free_func, copy_func,
nullptr, // value_peek_pointer
nullptr, // collect_format
diff --git a/glib/glibmm/value_custom.h b/glib/glibmm/value_custom.h
index 421fa28a..d8e486b5 100644
--- a/glib/glibmm/value_custom.h
+++ b/glib/glibmm/value_custom.h
@@ -33,11 +33,16 @@ namespace Glib
#ifndef DOXYGEN_SHOULD_SKIP_THIS
+//TODO: When we can break ABI, remove these extern "C" typedefs and
+// custom_boxed_type_register().
extern "C" {
typedef void (*ValueInitFunc)(GValue*);
typedef void (*ValueFreeFunc)(GValue*);
typedef void (*ValueCopyFunc)(const GValue*, GValue*);
}
+using ValueInitCppFuncType = void (*) (GValue*);
+using ValueFreeCppFuncType = void (*) (GValue*);
+using ValueCopyCppFuncType = void (*) (const GValue*, GValue*);
/* When using Glib::Value<T> with custom types, each T will be registered
* as subtype of G_TYPE_BOXED, via this function. The type_name argument
@@ -45,8 +50,14 @@ typedef void (*ValueCopyFunc)(const GValue*, GValue*);
*/
GLIBMM_API
+GType custom_boxed_type_cpp_register(
+ const char* type_name, ValueInitCppFuncType init_func,
+ ValueFreeCppFuncType free_func, ValueCopyCppFuncType copy_func);
+
+GLIBMM_API
GType custom_boxed_type_register(
- const char* type_name, ValueInitFunc init_func, ValueFreeFunc free_func, ValueCopyFunc copy_func);
+ const char* type_name, ValueInitFunc init_func,
+ ValueFreeFunc free_func, ValueCopyFunc copy_func);
/* When using Glib::Value<T*> or Glib::Value<const T*> with custom types,
* each T* or const T* will be registered as a subtype of G_TYPE_POINTER,
@@ -267,7 +278,7 @@ Value<T, Enable>::value_type()
{
if (!custom_type_)
{
- custom_type_ = Glib::custom_boxed_type_register(typeid(CppType).name(),
+ custom_type_ = Glib::custom_boxed_type_cpp_register(typeid(CppType).name(),
&Value<T>::value_init_func, &Value<T>::value_free_func, &Value<T>::value_copy_func);
}
return custom_type_;
diff --git a/tests/glibmm_value/main.cc b/tests/glibmm_value/main.cc
index a824f948..4aea37cc 100644
--- a/tests/glibmm_value/main.cc
+++ b/tests/glibmm_value/main.cc
@@ -28,6 +28,13 @@ test()
const auto v = value.get();
assert(v.bar == 1);
+
+ // Make a copy
+ Glib::Value<Foo> value2;
+ value2.init(Glib::Value<Foo>::value_type()); // TODO: Avoid this step?
+ value2 = value;
+ const auto v2 = value2.get();
+ assert(v2.bar == 1);
}
{