GObject ------- Every GObject is attached a C++ class instance that provides the C++ bindings for this object. This is done using the system described below. Every C++ binding class has a "constructor" method which is autogenerated by codegen and it simply creates an instance of this class. This method is not a member of the class, but it is a friend of the class, so that it can call the private constructor. The constructor and the friend declaration are both declared inside the Q*_WRAPPER macro at the top of the class definition. A pointer to this constructor method is then saved inside the quark data of the GType that this class provides bindings for. The code that does this is also generated by codegen and it is called from the global init() function of the relevant namespace (QGlib::init() and QGst::init()). When the C object is first wrapped using RefPointer::wrap(), the wrap method checks the GType of this C object and constructs a C++ class instance that best matches the GType of the object. That means that if the given GType has a pointer to a constructor method saved in its qdata, then it is used, otherwise, it tries the GType of the parent and this goes on recursively. In the worst case, a QGlib::Object instance will be created, which is the wrapper for GObject, the parent of all object types. After the C++ class instance has been created, a pointer to it is saved inside the GObject instance qdata. This allows it to be reused; if for some reason all the references to this instance are dropped from the C++ side and then later RefPointer::wrap() is called again on the same C instance, it reuses the same C++ instance that was created earlier. The C++ instance is finally deleted when the C instance is also deleted. A GObject weak reference is used internally to get a notification when the C instance has been deleted. GObject Interfaces ------------------ Interfaces are handled in a similar way, but not exactly the same. Interfaces are generally implemented by GObject subclasses in a way that resembles multiple inheritance. In C++ we use multiple inheritance to simulate this. So for example, because GstBin implements the GstChildProxy interface and inherits GstElement, in C++ the class is: class Bin : public Element, public ChildProxy Now in this case, if we have a QGst::Element pointer that is actually a QGst::Bin instance, the simplest way to cast to the ChildProxy interface is to use C++'s dynamic_cast(). However, it is not always possible to have a class that inherits from all the supported interfaces, since in many cases those interfaces are either dynamic or implemented in unknown subclasses. This is the case for example with the various GStreamer elements which are implemented inside plugins and as a result, their class definition is not known before runtime. So, for all those GStreamer elements, the C++ class that is generally created is QGst::Element - which does not inherit from any interface - and the interfaces are added dynamically when needed, in the following way: First, a GType check is performed to see if the element really implements the requested interface. If it does, a constructor method for the C++ class that wraps the interface is requested from the interface's GType qdata and this method is used to construct the interface's C++ instance, as it is done with GObject. This interface C++ instance is then also saved inside the GObject instance qdata, but using a different quark as a key for every interface, so that multiple interface C++ instances can be saved. This functionality is all hidden inside RefPointer::dynamicCast(), which hides the complexity from the user and offers it as if it was part of the programming language. GstMiniObject ------------- GstMiniObject is a special case, since it does not inherit from GObject, but is a boxed type instead. In general, the same technique as in GObject is used, with the most notable difference being that GstMiniObject has no qdata on its instance and no weak references, so the C++ class instance cannot be saved on the C instance and cannot be deleted when the C instance is deleted. To work this around, an external reference count is added on the C++ class instance, which is incremented and deincremented from RefPointer. Unfortunately this whole technique does not allow reuse of the C++ instance; the C++ instance is deleted as soon as all the RefPointers that point to it are destroyed, just like it would happen with QSharedPointer.