1 #ifndef _GLIBMM_OBJECT_H 2 #define _GLIBMM_OBJECT_H 3 4 /* Copyright 2002 The gtkmm Development Team 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 // X11 defines DestroyNotify and some other non-prefixed stuff, and it's too late to change that 21 // now, 22 // so let's give people a clue about the compilation errors that they will see: 23 #ifdef DestroyNotify 24 #error \ 25 "X11/Xlib.h seems to have been included before this header. Due to some commonly-named macros in X11/Xlib.h, it may only be included after any glibmm, gdkmm, or gtkmm headers." 26 #endif 27 28 #include <glibmmconfig.h> 29 #include <glibmm/objectbase.h> 30 #include <glibmm/wrap.h> 31 #include <glibmm/quark.h> 32 #include <glibmm/refptr.h> 33 #include <glibmm/utility.h> /* Could be private, but that would be tedious. */ 34 #include <glibmm/containerhandle_shared.h> /* Because its specializations may be here. */ 35 #include <glibmm/value.h> 36 #include <glib.h> /* for G_GNUC_NULL_TERMINATED */ 37 38 #ifndef DOXYGEN_SHOULD_SKIP_THIS 39 extern "C" { 40 using GObject = struct _GObject; 41 using GObjectClass = struct _GObjectClass; 42 } 43 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 44 45 namespace Glib 46 { 47 48 #ifndef DOXYGEN_SHOULD_SKIP_THIS 49 50 class GLIBMM_API Class; 51 class GLIBMM_API Object_Class; 52 class GLIBMM_API GSigConnectionNode; 53 54 /* ConstructParams::ConstructParams() takes a varargs list of properties 55 * and values, like g_object_new() does. This list will then be converted 56 * to a GParameter array, for use with g_object_newv(). No overhead is 57 * involved, since g_object_new() is just a wrapper around g_object_newv() 58 * as well. 59 * 60 * The advantage of an auxiliary ConstructParams object over g_object_new() 61 * is that the actual construction is always done in the Glib::Object ctor. 62 * This allows for neat tricks like easy creation of derived custom types, 63 * without adding special support to each ctor of every class. 64 * 65 * The comments in object.cc and objectbase.cc should explain in detail 66 * how this works. 67 */ 68 class GLIBMM_API ConstructParams 69 { 70 public: 71 const Glib::Class& glibmm_class; 72 unsigned int n_parameters; 73 G_GNUC_BEGIN_IGNORE_DEPRECATIONS 74 GParameter* parameters; 75 G_GNUC_END_IGNORE_DEPRECATIONS 76 77 explicit ConstructParams(const Glib::Class& glibmm_class_); 78 ConstructParams(const Glib::Class& glibmm_class_, const char* first_property_name, 79 ...) G_GNUC_NULL_TERMINATED; // warn if called without a trailing NULL pointer 80 ~ConstructParams() noexcept; 81 82 // The copy constructor is semantically required by the C++ compiler 83 // (since g++ 3.4) to be able to create temporary instances, depending 84 // on the usage context. Apparently the compiler will actually optimize 85 // away the copy, though. See bug #132300. 86 ConstructParams(const ConstructParams& other); 87 88 private: 89 // no copy assignment 90 ConstructParams& operator=(const ConstructParams&); 91 }; 92 93 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 94 95 class GLIBMM_API Object : virtual public ObjectBase 96 { 97 public: 98 #ifndef DOXYGEN_SHOULD_SKIP_THIS 99 using CppObjectType = Object; 100 using CppClassType = Object_Class; 101 using BaseObjectType = GObject; 102 using BaseClassType = GObjectClass; 103 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 104 105 // noncopyable 106 Object(const Object&) = delete; 107 Object& operator=(const Object&) = delete; 108 109 Object(Object&& src) noexcept; 110 Object& operator=(Object&& src) noexcept; 111 112 protected: 113 Object(); // For use by C++-only sub-types. 114 explicit Object(const Glib::ConstructParams& construct_params); 115 explicit Object(GObject* castitem); 116 ~Object() noexcept override; // It should only be deleted by the callback. 117 118 public: 119 // static RefPtr<Object> create(); //You must reimplement this in each derived class. 120 121 #ifndef DOXYGEN_SHOULD_SKIP_THIS 122 static GType get_type() G_GNUC_CONST; 123 static GType get_base_type() G_GNUC_CONST; 124 #endif 125 126 // GObject* gobj_copy(); //Give a ref-ed copy to someone. Use for direct struct access. 127 128 // Glib::Objects contain a list<Quark, pair<void*, DestroyNotify> > 129 // to store run time data added to the object at run time. 130 // TODO: Use slots instead: 131 void* get_data(const QueryQuark& key); 132 void set_data(const Quark& key, void* data); 133 using DestroyNotify = void (*)(gpointer data); 134 void set_data(const Quark& key, void* data, DestroyNotify notify); 135 void remove_data(const QueryQuark& quark); 136 // same as remove without notifying 137 void* steal_data(const QueryQuark& quark); 138 139 // convenience functions 140 // template <class T> 141 // void set_data_typed(const Quark& quark, const T& data) 142 // { set_data(quark, new T(data), delete_typed<T>); } 143 144 // template <class T> 145 // T& get_data_typed(const QueryQuark& quark) 146 // { return *static_cast<T*>(get_data(quark)); } 147 148 #ifndef DOXYGEN_SHOULD_SKIP_THIS 149 150 private: 151 friend class Glib::Object_Class; 152 static CppClassType object_class_; 153 154 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 155 156 // Glib::Object can not be dynamic because it lacks a float state. 157 // virtual void set_manage(); 158 }; 159 160 // For some (proably, more spec-compliant) compilers, these specializations must 161 // be next to the objects that they use. 162 #ifndef GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION 163 #ifndef DOXYGEN_SHOULD_SKIP_THIS /* hide the specializations */ 164 165 namespace Container_Helpers 166 { 167 168 /** Partial specialization for pointers to GObject instances. 169 * @ingroup ContHelpers 170 * The C++ type is always a Glib::RefPtr<>. 171 */ 172 template <class T> 173 struct TypeTraits<Glib::RefPtr<T>> 174 { 175 using CppType = Glib::RefPtr<T>; 176 using CType = typename T::BaseObjectType*; 177 using CTypeNonConst = typename T::BaseObjectType*; 178 179 static CType to_c_type(const CppType& ptr) { return Glib::unwrap(ptr); } 180 static CType to_c_type(CType ptr) { return ptr; } 181 static CppType to_cpp_type(CType ptr) 182 { 183 // return Glib::wrap(ptr, true); 184 185 // We copy/paste the wrap() implementation here, 186 // because we can not use a specific Glib::wrap(CType) overload here, 187 // because that would be "dependent", and g++ 3.4 does not allow that. 188 // The specific Glib::wrap() overloads don't do anything special anyway. 189 GObject* cobj = (GObject*)const_cast<CTypeNonConst>(ptr); 190 return Glib::RefPtr<T>(dynamic_cast<T*>(Glib::wrap_auto(cobj, true /* take_copy */))); 191 // We use dynamic_cast<> in case of multiple inheritance. 192 } 193 194 static void release_c_type(CType ptr) 195 { 196 GLIBMM_DEBUG_UNREFERENCE(nullptr, ptr); 197 g_object_unref(ptr); 198 } 199 }; 200 201 // This confuses the SUN Forte compiler, so we ifdef it out: 202 #ifdef GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS 203 204 /** Partial specialization for pointers to const GObject instances. 205 * @ingroup ContHelpers 206 * The C++ type is always a Glib::RefPtr<>. 207 */ 208 template <class T> 209 struct TypeTraits<Glib::RefPtr<const T>> 210 { 211 using CppType = Glib::RefPtr<const T>; 212 using CType = const typename T::BaseObjectType*; 213 using CTypeNonConst = typename T::BaseObjectType*; 214 215 static CType to_c_type(const CppType& ptr) { return Glib::unwrap(ptr); } 216 static CType to_c_type(CType ptr) { return ptr; } 217 static CppType to_cpp_type(CType ptr) 218 { 219 // return Glib::wrap(ptr, true); 220 221 // We copy/paste the wrap() implementation here, 222 // because we can not use a specific Glib::wrap(CType) overload here, 223 // because that would be "dependent", and g++ 3.4 does not allow that. 224 // The specific Glib::wrap() overloads don't do anything special anyway. 225 GObject* cobj = (GObject*)(ptr); 226 return Glib::RefPtr<const T>( 227 dynamic_cast<const T*>(Glib::wrap_auto(cobj, true /* take_copy */))); 228 // We use dynamic_cast<> in case of multiple inheritance. 229 } 230 231 static void release_c_type(CType ptr) 232 { 233 GLIBMM_DEBUG_UNREFERENCE(nullptr, ptr); 234 g_object_unref(const_cast<CTypeNonConst>(ptr)); 235 } 236 }; 237 238 #endif /* GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS */ 239 240 } // namespace Container_Helpers 241 242 template <class T, class PtrT> 243 inline PtrT 244 Value_Pointer<T, PtrT>::get_(Glib::Object*) const 245 { 246 return dynamic_cast<T*>(get_object()); 247 } 248 249 /** Partial specialization for RefPtr<> to Glib::Object. 250 * @ingroup glibmmValue 251 */ 252 template <class T> 253 class Value<Glib::RefPtr<T>> : public ValueBase_Object 254 { 255 public: 256 using CppType = Glib::RefPtr<T>; 257 using CType = typename T::BaseObjectType*; 258 259 static GType value_type() { return T::get_base_type(); } 260 261 void set(const CppType& data) { set_object(data.operator->()); } 262 CppType get() const { return Glib::RefPtr<T>::cast_dynamic(get_object_copy()); } 263 }; 264 265 // The SUN Forte Compiler has a problem with this: 266 #ifdef GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS 267 268 /** Partial specialization for RefPtr<> to const Glib::Object. 269 * @ingroup glibmmValue 270 */ 271 template <class T> 272 class Value<Glib::RefPtr<const T>> : public ValueBase_Object 273 { 274 public: 275 using CppType = Glib::RefPtr<const T>; 276 using CType = typename T::BaseObjectType*; 277 278 static GType value_type() { return T::get_base_type(); } 279 280 void set(const CppType& data) { set_object(const_cast<T*>(data.operator->())); } 281 CppType get() const { return Glib::RefPtr<T>::cast_dynamic(get_object_copy()); } 282 }; 283 #endif /* GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS */ 284 285 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 286 #endif /* GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION */ 287 288 } // namespace Glib 289 290 #endif /* _GLIBMM_OBJECT_H */ 291