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