1 #ifndef _GLIBMM_WRAP_H
2 #define _GLIBMM_WRAP_H
3
4 /* Copyright (C) 1998-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 #include <glib-object.h>
21 #include <glibmm/refptr.h>
22 #include <glibmm/objectbase.h>
23
24 namespace Glib
25 {
26
27 #ifndef DOXYGEN_SHOULD_SKIP_THIS
28
29 class GLIBMM_API ObjectBase;
30 class GLIBMM_API Object;
31
32 // Type of the per-class wrap_new() functions.
33 using WrapNewFunction = Glib::ObjectBase*(*)(GObject*);
34
35 // Setup and free the structures used by wrap_register().
36 // Both functions might be called more than once.
37 GLIBMM_API
38 void wrap_register_init();
39
40 GLIBMM_API
41 void wrap_register_cleanup();
42
43 // Register a new type for auto allocation.
44 GLIBMM_API
45 void wrap_register(GType type, WrapNewFunction func);
46
47 // Return the current C++ wrapper instance of the GObject,
48 // or automatically generate a new wrapper if there's none.
49 GLIBMM_API
50 Glib::ObjectBase* wrap_auto(GObject* object, bool take_copy = false);
51
52 /** Create a C++ instance of a known C++ type that is mostly closely associated with the GType of
53 * the C object.
54 * @param object The C object which should be placed in a new C++ instance.
55 * @param interface_gtype The returned instance will implement this interface. Otherwise it will be
56 * NULL.
57 */
58 GLIBMM_API
59 Glib::ObjectBase* wrap_create_new_wrapper_for_interface(GObject* object, GType interface_gtype);
60
61 // Return the current C++ wrapper instance of the GObject,
62 // or automatically generate a new wrapper if there's none.
63 template <class TInterface>
64 TInterface*
65 wrap_auto_interface(GObject* object, bool take_copy = false)
66 {
67 if (!object)
68 return nullptr;
69
70 // Look up current C++ wrapper instance:
71 ObjectBase* pCppObject = ObjectBase::_get_current_wrapper(object);
72
73 if (!pCppObject)
74 {
75 // There's not already a wrapper: generate a new C++ instance.
76 // We use exact_type_only=true avoid creating Glib::Object for interfaces of unknown
77 // implementation,
78 // because we do not want a C++ object that does not dynamic_cast to the expected interface
79 // type.
80 pCppObject = wrap_create_new_wrapper_for_interface(object, TInterface::get_base_type());
81 }
82
83 // If no exact wrapper was created,
84 // create an instance of the interface,
85 // so we at least get the expected type:
86 TInterface* result = nullptr;
87 if (pCppObject)
88 {
89 result = dynamic_cast<TInterface*>(pCppObject);
90 if (!result)
91 {
92 g_warning("Glib::wrap_auto_interface(): The C++ instance (%s) does not dynamic_cast to the "
93 "interface.\n",
94 typeid(*pCppObject).name());
95 }
96 }
97 else
98 result = new TInterface((typename TInterface::BaseObjectType*)object);
99
100 // take_copy=true is used where the GTK+ function doesn't do
101 // an extra ref for us, and always for plain struct members.
102 if (take_copy && result)
103 result->reference();
104
105 return result;
106 }
107
108 #endif // DOXYGEN_SHOULD_SKIP_THIS
109
110 // Get a C++ instance that wraps the C instance.
111 // This always returns the same C++ instance for the same C instance.
112 // Each wrapper has it's own override of Glib::wrap().
113 // use take_copy = true when wrapping a struct member.
114 // TODO: move to object.h ?
115 /** @relates Glib::Object */
116 GLIBMM_API
117 Glib::RefPtr<Glib::Object> wrap(GObject* object, bool take_copy = false);
118
119 /** Get the underlying C instance from the C++ instance. This is just
120 * like calling gobj(), but it does its own check for a NULL pointer.
121 */
122 template <class T>
123 inline typename T::BaseObjectType*
unwrap(T * ptr)124 unwrap(T* ptr)
125 {
126 return (ptr) ? ptr->gobj() : nullptr;
127 }
128
129 /** Get the underlying C instance from the C++ instance. This is just
130 * like calling gobj(), but it does its own check for a NULL pointer.
131 */
132 template <class T>
133 inline const typename T::BaseObjectType*
unwrap(const T * ptr)134 unwrap(const T* ptr)
135 {
136 return (ptr) ? ptr->gobj() : nullptr;
137 }
138
139 /** Get the underlying C instance from the C++ instance. This is just
140 * like calling gobj(), but it does its own check for a NULL pointer.
141 */
142 template <class T>
143 inline typename T::BaseObjectType*
unwrap(const Glib::RefPtr<T> & ptr)144 unwrap(const Glib::RefPtr<T>& ptr)
145 {
146 return (ptr) ? ptr->gobj() : nullptr;
147 }
148
149 /** Get the underlying C instance from the C++ instance. This is just
150 * like calling gobj(), but it does its own check for a NULL pointer.
151 */
152 template <class T>
153 inline const typename T::BaseObjectType*
unwrap(const Glib::RefPtr<const T> & ptr)154 unwrap(const Glib::RefPtr<const T>& ptr)
155 {
156 return (ptr) ? ptr->gobj() : nullptr;
157 }
158
159 // This unwrap_copy() overload is intended primarily for classes wrapped as
160 // _CLASS_BOXEDTYPE, _CLASS_OPAQUE_COPYABLE or _CLASS_OPAQUE_REFCOUNTED,
161 // where the C++ objects are not stored in Glib::RefPtr<>s. They have a const
162 // gobj_copy() member that returns a non-const pointer to the underlying C instance.
163 /** Get the underlying C instance from the C++ instance and acquire a
164 * reference or copy. This is just like calling gobj_copy(), but it does its own
165 * check for a NULL pointer to the underlying C instance.
166 */
167 template <class T>
168 inline typename T::BaseObjectType*
unwrap_copy(const T & obj)169 unwrap_copy(const T& obj)
170 {
171 return obj.gobj() ? obj.gobj_copy() : nullptr;
172 }
173
174 /** Get the underlying C instance from the C++ instance and acquire a
175 * reference. This is just like calling gobj_copy(), but it does its own
176 * check for a NULL pointer.
177 */
178 template <class T>
179 inline typename T::BaseObjectType*
unwrap_copy(const Glib::RefPtr<T> & ptr)180 unwrap_copy(const Glib::RefPtr<T>& ptr)
181 {
182 return (ptr) ? ptr->gobj_copy() : nullptr;
183 }
184
185 /** Get the underlying C instance from the C++ instance and acquire a
186 * reference. This is just like calling gobj_copy(), but it does its own
187 * check for a NULL pointer.
188 */
189 template <class T>
190 inline const typename T::BaseObjectType*
unwrap_copy(const Glib::RefPtr<const T> & ptr)191 unwrap_copy(const Glib::RefPtr<const T>& ptr)
192 {
193 return (ptr) ? ptr->gobj_copy() : nullptr;
194 }
195
196 } // namespace Glib
197
198 #endif /* _GLIBMM_WRAP_H */
199