diff options
author | Kjell Ahlstedt <kjellahlstedt@gmail.com> | 2023-03-31 19:00:02 +0200 |
---|---|---|
committer | Kjell Ahlstedt <kjellahlstedt@gmail.com> | 2023-03-31 19:00:02 +0200 |
commit | 07fbd1f0e0a68fb3b130fe9d0b0f5f338346746a (patch) | |
tree | 4d3182fa5e2e9c99b6fd31519f0c6594ef291041 | |
parent | 7ff8b74a47059edbba7a9f9424fa0022943bc6ec (diff) | |
download | glibmm-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.cc | 55 | ||||
-rw-r--r-- | glib/glibmm/value_custom.h | 15 | ||||
-rw-r--r-- | tests/glibmm_value/main.cc | 7 |
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); } { |