From patchwork Mon Dec 12 20:18:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Liguori X-Patchwork-Id: 130900 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0B7CFB6FA0 for ; Tue, 13 Dec 2011 09:19:36 +1100 (EST) Received: from localhost ([::1]:53724 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RaEDY-0005Nq-Ks for incoming@patchwork.ozlabs.org; Mon, 12 Dec 2011 17:19:28 -0500 Received: from eggs.gnu.org ([140.186.70.92]:42261) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RaCPO-0005IB-Ll for qemu-devel@nongnu.org; Mon, 12 Dec 2011 15:23:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RaCPL-0000nv-Ue for qemu-devel@nongnu.org; Mon, 12 Dec 2011 15:23:34 -0500 Received: from cpe-70-123-132-139.austin.res.rr.com ([70.123.132.139]:44603 helo=localhost6.localdomain6) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RaCPL-0000no-7a for qemu-devel@nongnu.org; Mon, 12 Dec 2011 15:23:31 -0500 Received: from localhost6.localdomain6 (localhost.localdomain [127.0.0.1]) by localhost6.localdomain6 (8.14.4/8.14.4/Debian-2ubuntu1) with ESMTP id pBCKNJW4032618; Mon, 12 Dec 2011 14:23:19 -0600 Received: (from anthony@localhost) by localhost6.localdomain6 (8.14.4/8.14.4/Submit) id pBCKNHgw032615; Mon, 12 Dec 2011 14:23:17 -0600 From: Anthony Liguori To: qemu-devel@nongnu.org Date: Mon, 12 Dec 2011 14:18:22 -0600 Message-Id: <1323721273-32404-27-git-send-email-aliguori@us.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1323721273-32404-1-git-send-email-aliguori@us.ibm.com> References: <1323721273-32404-1-git-send-email-aliguori@us.ibm.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 70.123.132.139 Cc: Kevin Wolf , Peter Maydell , Anthony Liguori , Stefan Hajnoczi , Jan Kiszka , Markus Armbruster , Luiz Capitulino Subject: [Qemu-devel] [PATCH v3 026/197] qom: add qobject X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Anthony Liguori --- Makefile.objs | 2 + hw/qobject.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/qobject.h | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 936 insertions(+), 0 deletions(-) create mode 100644 hw/qobject.c create mode 100644 hw/qobject.h diff --git a/Makefile.objs b/Makefile.objs index 67e1ae5..8e629f1 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -123,6 +123,8 @@ common-obj-$(CONFIG_WIN32) += version.o common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o spice-qemu-char.o +common-obj-y += qobject.o + audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o audio-obj-$(CONFIG_SDL) += sdlaudio.o audio-obj-$(CONFIG_OSS) += ossaudio.o diff --git a/hw/qobject.c b/hw/qobject.c new file mode 100644 index 0000000..54398ab --- /dev/null +++ b/hw/qobject.c @@ -0,0 +1,463 @@ +/* + * QEMU Object Model + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qobject.h" + +#define MAX_INTERFACES 32 + +typedef struct QInterfaceImpl +{ + const char *parent; + void (*interface_initfn)(QObjectClass *class); + QType type; +} QInterfaceImpl; + +typedef struct QTypeImpl +{ + const char *name; + QType type; + + size_t class_size; + + size_t instance_size; + + void (*base_init)(QObjectClass *klass); + void (*base_finalize)(QObjectClass *klass); + + void (*class_init)(QObjectClass *klass); + void (*class_finalize)(QObjectClass *klass); + + void (*instance_init)(QObject *obj); + void (*instance_finalize)(QObject *obj); + + bool abstract; + + const char *parent; + + QObjectClass *class; + + int num_interfaces; + QInterfaceImpl interfaces[MAX_INTERFACES]; +} QTypeImpl; + +static int num_types = 1; +static QTypeImpl type_table[1024]; + +QType qtype_register_static(const QTypeInfo *info) +{ + QType type = num_types++; + QTypeImpl *ti; + + ti = &type_table[type]; + + assert(info->name != NULL); + + ti->name = info->name; + ti->parent = info->parent; + ti->type = type; + + ti->class_size = info->class_size; + ti->instance_size = info->instance_size; + + ti->base_init = info->base_init; + ti->base_finalize = info->base_finalize; + + ti->class_init = info->class_init; + ti->class_finalize = info->class_finalize; + + ti->instance_init = info->instance_init; + ti->instance_finalize = info->instance_finalize; + + ti->abstract = info->abstract; + + if (info->interfaces) { + int i; + + for (i = 0; info->interfaces[i].type; i++) { + ti->interfaces[i].parent = info->interfaces[i].type; + ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; + ti->num_interfaces++; + } + } + + return type; +} + +static QType qtype_register_anonymous(const QTypeInfo *info) +{ + QType type = num_types++; + QTypeImpl *ti; + char buffer[32]; + static int count; + + ti = &type_table[type]; + + snprintf(buffer, sizeof(buffer), "", count++); + ti->name = g_strdup(buffer); + ti->parent = g_strdup(info->parent); + ti->type = type; + + ti->class_size = info->class_size; + ti->instance_size = info->instance_size; + + ti->base_init = info->base_init; + ti->base_finalize = info->base_finalize; + + ti->class_init = info->class_init; + ti->class_finalize = info->class_finalize; + + ti->instance_init = info->instance_init; + ti->instance_finalize = info->instance_finalize; + + if (info->interfaces) { + int i; + + for (i = 0; info->interfaces[i].type; i++) { + ti->interfaces[i].parent = info->interfaces[i].type; + ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; + ti->num_interfaces++; + } + } + + return type; +} + +static QTypeImpl *qtype_get_instance(QType type) +{ + assert(type != 0); + assert(type < num_types); + + return &type_table[type]; +} + +QType qtype_get_by_name(const char *name) +{ + int i; + + if (name == NULL) { + return 0; + } + + for (i = 1; i < num_types; i++) { + if (strcmp(name, type_table[i].name) == 0) { + return i; + } + } + + return 0; +} + +static void qtype_class_base_init(QTypeImpl *base_ti, const char *typename) +{ + QTypeImpl *ti; + + if (!typename) { + return; + } + + ti = qtype_get_instance(qtype_get_by_name(typename)); + + qtype_class_base_init(base_ti, ti->parent); + + if (ti->base_init) { + ti->base_init(base_ti->class); + } +} + +static size_t qtype_class_get_size(QTypeImpl *ti) +{ + if (ti->class_size) { + return ti->class_size; + } + + if (ti->parent) { + return qtype_class_get_size(qtype_get_instance(qtype_get_by_name(ti->parent))); + } + + return sizeof(QObjectClass); +} + +static void qtype_class_interface_init(QTypeImpl *ti, QInterfaceImpl *iface) +{ + QTypeInfo info = { + .instance_size = sizeof(QInterface), + .parent = iface->parent, + .class_size = sizeof(QInterfaceClass), + .class_init = iface->interface_initfn, + .abstract = true, + }; + + iface->type = qtype_register_anonymous(&info); +} + +static void qtype_class_init(QTypeImpl *ti) +{ + size_t class_size = sizeof(QObjectClass); + int i; + + if (ti->class) { + return; + } + + ti->class_size = qtype_class_get_size(ti); + + ti->class = g_malloc0(ti->class_size); + ti->class->type = ti->type; + + if (ti->parent) { + QTypeImpl *ti_parent; + + ti_parent = qtype_get_instance(qtype_get_by_name(ti->parent)); + + qtype_class_init(ti_parent); + + class_size = ti_parent->class_size; + assert(ti_parent->class_size <= ti->class_size); + + memcpy((void *)ti->class + sizeof(QObjectClass), + (void *)ti_parent->class + sizeof(QObjectClass), + ti_parent->class_size - sizeof(QObjectClass)); + } + + memset((void *)ti->class + class_size, 0, ti->class_size - class_size); + + qtype_class_base_init(ti, ti->parent); + + for (i = 0; i < ti->num_interfaces; i++) { + qtype_class_interface_init(ti, &ti->interfaces[i]); + } + + if (ti->class_init) { + ti->class_init(ti->class); + } +} + +static void qobject_interface_init(QObject *obj, QInterfaceImpl *iface) +{ + QTypeImpl *ti = qtype_get_instance(iface->type); + QInterface *iface_obj; + + iface_obj = QINTERFACE(qobject_new(ti->name)); + iface_obj->obj = obj; + + obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj); +} + +static void qobject_init(QObject *obj, const char *typename) +{ + QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); + int i; + + if (ti->parent) { + qobject_init(obj, ti->parent); + } + + for (i = 0; i < ti->num_interfaces; i++) { + qobject_interface_init(obj, &ti->interfaces[i]); + } + + if (ti->instance_init) { + ti->instance_init(obj); + } +} + +void qobject_initialize(void *data, const char *typename) +{ + QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); + QObject *obj = data; + + g_assert(ti->instance_size >= sizeof(QObjectClass)); + + qtype_class_init(ti); + + g_assert(ti->abstract == false); + + memset(obj, 0, ti->instance_size); + + obj->class = ti->class; + + qobject_init(obj, typename); +} + +static void qobject_deinit(QObject *obj, const char *typename) +{ + QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); + + if (ti->instance_finalize) { + ti->instance_finalize(obj); + } + + while (obj->interfaces) { + QInterface *iface_obj = obj->interfaces->data; + obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces); + qobject_delete(QOBJECT(iface_obj)); + } + + if (ti->parent) { + qobject_init(obj, ti->parent); + } +} + +void qobject_finalize(void *data) +{ + QObject *obj = data; + QTypeImpl *ti = qtype_get_instance(obj->class->type); + + qobject_deinit(obj, ti->name); +} + +const char *qtype_get_name(QType type) +{ + QTypeImpl *ti = qtype_get_instance(type); + return ti->name; +} + +QObject *qobject_new(const char *typename) +{ + QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); + QObject *obj; + + obj = g_malloc(ti->instance_size); + qobject_initialize(obj, typename); + + return obj; +} + +void qobject_delete(QObject *obj) +{ + qobject_finalize(obj); + g_free(obj); +} + +bool qobject_is_type(QObject *obj, const char *typename) +{ + QType target_type = qtype_get_by_name(typename); + QType type = obj->class->type; + GSList *i; + + /* Check if typename is a direct ancestor of type */ + while (type) { + QTypeImpl *ti = qtype_get_instance(type); + + if (ti->type == target_type) { + return true; + } + + type = qtype_get_by_name(ti->parent); + } + + /* Check if obj has an interface of typename */ + for (i = obj->interfaces; i; i = i->next) { + QInterface *iface = i->data; + + if (qobject_is_type(QOBJECT(iface), typename)) { + return true; + } + } + + return false; +} + +QObject *qobject_dynamic_cast(QObject *obj, const char *typename) +{ + GSList *i; + + /* Check if typename is a direct ancestor */ + if (qobject_is_type(obj, typename)) { + return obj; + } + + /* Check if obj has an interface of typename */ + for (i = obj->interfaces; i; i = i->next) { + QInterface *iface = i->data; + + if (qobject_is_type(QOBJECT(iface), typename)) { + return QOBJECT(iface); + } + } + + /* Check if obj is an interface and it's containing object is a direct ancestor of typename */ + if (qobject_is_type(obj, TYPE_QINTERFACE)) { + QInterface *iface = QINTERFACE(obj); + + if (qobject_is_type(iface->obj, typename)) { + return iface->obj; + } + } + + return NULL; +} + + +static void register_interface(void) +{ + static QTypeInfo interface_info = { + .name = TYPE_QINTERFACE, + .instance_size = sizeof(QInterface), + .abstract = true, + }; + + qtype_register_static(&interface_info); +} + +device_init(register_interface); + +QObject *qobject_dynamic_cast_assert(QObject *obj, const char *typename) +{ + QObject *inst; + + inst = qobject_dynamic_cast(obj, typename); + + if (!inst) { + fprintf(stderr, "Object %p is not an instance of type %s\n", obj, typename); + abort(); + } + + return inst; +} + +QObjectClass *qobject_check_class(QObjectClass *class, const char *typename) +{ + QType target_type = qtype_get_by_name(typename); + QType type = class->type; + + while (type) { + QTypeImpl *ti = qtype_get_instance(type); + + if (ti->type == target_type) { + return class; + } + + type = qtype_get_by_name(ti->parent); + } + + fprintf(stderr, "Object %p is not an instance of type %d\n", class, (int)type); + abort(); + + return NULL; +} + +const char *qobject_get_type(QObject *obj) +{ + return qtype_get_name(obj->class->type); +} + +QObjectClass *qobject_get_class(QObject *obj) +{ + return obj->class; +} + +QObjectClass *qobject_get_super(QObject *obj) +{ + return qtype_get_instance(qtype_get_by_name(qtype_get_instance(obj->class->type)->parent))->class; +} + diff --git a/hw/qobject.h b/hw/qobject.h new file mode 100644 index 0000000..f20ed1c --- /dev/null +++ b/hw/qobject.h @@ -0,0 +1,471 @@ +/* + * QEMU Object Model + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QOBJECT_H +#define QOBJECT_H + +#include "qemu-common.h" + +typedef uint64_t QType; + +typedef struct QObjectClass QObjectClass; +typedef struct QObject QObject; + +typedef struct QTypeInfo QTypeInfo; + +typedef struct QInterfaceClass QInterfaceClass; +typedef struct QInterface QInterface; +typedef struct QInterfaceInfo QInterfaceInfo; + +/** + * @QObjectClass: + * + * The base for all classes. The only thing that @QObjectClass contains is an + * integer type handle. + */ +struct QObjectClass +{ + /** + * @type the handle of the type for a class + */ + QType type; +}; + +/** + * @QObject: + * + * The base for all objects. The first member of this object is a pointer to + * a @QObjectClass. Since C guarantees that the first member of a structure + * always begins at byte 0 of that structure, as long as any sub-object places + * its parent as the first member, we can cast directly to a @QObject. + * + * As a result, @QObject contains a reference to the objects type as its + * first member. This allows identification of the real type of the object at + * run time. + * + * @QObject also contains a list of @QInterfaces that this object + * implements. + */ +struct QObject +{ + /** + * @class the type of the instantiated object. + */ + QObjectClass *class; + + /** + * @interfaces a list of @QInterface objects implemented by this object + */ + GSList *interfaces; +}; + +/** + * @QTypeInfo: + * + */ +struct QTypeInfo +{ + /** + * @name the name of the type + */ + const char *name; + + /** + * @parent the name of the parent type + */ + const char *parent; + + /** + * Instance Initialization + * + * This functions manage the instance construction and destruction of a + * type. + */ + + /** + * @instance_size the size of the object (derivative of @QObject). If + * @instance_size is 0, then the size of the object will be the size of the + * parent object. + */ + size_t instance_size; + + /** + * @instance_init + * + * This function is called to initialize an object. The parent class will + * have already been initialized so the type is only responsible for + * initializing its own members. + */ + void (*instance_init)(QObject *obj); + + /** + * @instance_finalize + * + * This function is called during object destruction. This is called before + * the parent @instance_finalize function has been called. An object should + * only free the members that are unique to its type in this function. + */ + void (*instance_finalize)(QObject *obj); + + /** + * @abstract + * + * If this field is true, then the class is considered abstract and cannot + * be directly instantiated. + */ + bool abstract; + + /** + * Class Initialization + * + * Before an object is initialized, the class for the object must be + * initialized. There is only one class object for all instance objects + * that is created lazily. + * + * Classes are initialized by first initializing any parent classes (if + * necessary). After the parent class object has initialized, it will be + * copied into the current class object and any additional storage in the + * class object is zero filled. + * + * The effect of this is that classes automatically inherit any virtual + * function pointers that the parent class has already initialized. All + * other fields will be zero filled. + * + * After this initial copy, @base_init is invoked. This is meant to handle + * the case where a class may have a dynamic field that was copied via + * a shallow copy but needs to be deep copied. @base_init is called for + * each parent class but not for the class being instantiated. + * + * Once all of the parent classes have been initialized and their @base_init + * functions have been called, @class_init is called to let the class being + * instantiated provide default initialize for it's virtual functions. + */ + + /** + * @class_size the size of the class object (derivative of @QObjectClass) + * for this object. If @class_size is 0, then the size of the class will be + * assumed to be the size of the parent class. This allows a type to avoid + * implementing an explicit class type if they are not adding additional + * virtual functions. + */ + size_t class_size; + + /** + * @base_init + * + * This function is called after memcpy()'ing the base class into the new + * class to reinitialize any members that require deep copy. + */ + void (*base_init)(QObjectClass *klass); + + /** + * @base_finalize + * + * This function is called during a class's destruction and is meant to + * allow any dynamic parameters allocated by @base_init to be released. + */ + void (*base_finalize)(QObjectClass *klass); + + /** + * @class_init + * + * This function is called after all parent class initialization has occured + * to allow a class to set its default virtual method pointers. This is + * also the function to use to override virtual methods from a parent class. + */ + void (*class_init)(QObjectClass *klass); + + /** + * @class_finalize + * + * This function is called during class destruction and is meant to release + * and dynamic parameters allocated by @class_init. + */ + void (*class_finalize)(QObjectClass *klass); + + /** + * QInterfaces + * + * QInterfaces allow a limited form of multiple inheritance. Instances are + * similar to normal types except for the fact that are only defined by + * their classes and never carry any state. You can cast an object to one + * of its @QInterface types and vice versa. + */ + + /** + * @interfaces the list of interfaces associated with this type. This + * should point to a static array that's terminated with a zero filled + * element. + */ + QInterfaceInfo *interfaces; +}; + +/** + * @QOBJECT + * + * Converts an object to a @QObject. Since all objects are @QObjects, + * this function will always succeed. + */ +#define QOBJECT(obj) \ + ((QObject *)(obj)) + +/** + * @QOBJECT_CHECK + * + * A type safe version of @qobject_dynamic_cast_assert. Typically each class + * will define a macro based on this type to perform type safe dynamic_casts to + * this object type. + * + * If an invalid object is passed to this function, a run time assert will be + * generated. + */ +#define QOBJECT_CHECK(type, obj, name) \ + ((type *)qobject_dynamic_cast_assert((QObject *)(obj), (name))) + +/** + * @QOBJECT_CLASS_CHECK + * + * A type safe version of @qobject_check_class. This macro is typically wrapped + * by each type to perform type safe casts of a class to a specific class type. + */ +#define QOBJECT_CLASS_CHECK(class, obj, name) \ + ((class *)qobject_check_class((QObjectClass *)(obj), (name))) + +/** + * @QOBJECT_GET_CLASS + * + * This function will return a specific class for a given object. Its generally + * used by each type to provide a type safe macro to get a specific class type + * from an object. + */ +#define QOBJECT_GET_CLASS(class, obj, name) \ + QOBJECT_CLASS_CHECK(class, qobject_get_class(QOBJECT(obj)), name) + +/** + * @QQInterface: + * + * The base for all QInterfaces. This is a subclass of QObject. Subclasses + * of @QInterface should never have an instance that contains anything other + * than a single @QInterface member. + */ +struct QInterface +{ + /** + * @parent base class + */ + QObject parent; + + /* private */ + + /** + * @obj a pointer to the object that implements this interface. This is + * used to allow casting from an interface to the base object. + */ + QObject *obj; +}; + +/** + * @QInterfaceClass: + * + * The class for all interfaces. Subclasses of this class should only add + * virtual methods. + */ +struct QInterfaceClass +{ + /** + * @parent_class the base class + */ + QObjectClass parent_class; +}; + +/** + * @QInterfaceInfo: + * + * The information associated with an interface. + */ +struct QInterfaceInfo +{ + /** + * @type the name of the interface + */ + const char *type; + + /** + * @interface_initfn is called during class initialization and is used to + * initialize an interface associated with a class. This function should + * initialize any default virtual functions for a class and/or override + * virtual functions in a parent class. + */ + void (*interface_initfn)(QObjectClass *class); +}; + +#define TYPE_QINTERFACE "interface" +#define QINTERFACE(obj) QOBJECT_CHECK(QInterface, obj, TYPE_QINTERFACE) + +/** + * @qobject_new: + * + * This function will initialize a new object using heap allocated memory. This + * function should be paired with @qobject_delete to free the resources + * associated with the object. + * + * @typename: The name of the type of the object to instantiate + * + * Returns: The newly allocated and instantiated object. + * + */ +QObject *qobject_new(const char *typename); + +/** + * @qobject_delete: + * + * Finalize an object and then free the memory associated with it. This should + * be paired with @qobject_new to free the resources associated with an object. + * + * @obj: The object to free. + * + */ +void qobject_delete(QObject *obj); + +/** + * @qobject_initialize: + * + * This function will initialize an object. The memory for the object should + * have already been allocated. + * + * @obj: A pointer to the memory to be used for the object. + * + * @typename: The name of the type of the object to instantiate + * + */ +void qobject_initialize(void *obj, const char *typename); + +/** + * @qobject_finalize: + * + * This function destroys and object without freeing the memory associated with + * it. + * + * @obj: The object to finalize. + * + */ +void qobject_finalize(void *obj); + +/** + * @qobject_dynamic_cast: + * + * This function will determine if @obj is-a @typename. @obj can refer to an + * object or an interface associated with an object. + * + * @obj: The object to cast. + * + * @typename: The @typename + * + * Returns: + * + */ +QObject *qobject_dynamic_cast(QObject *obj, const char *typename); + +/** + * @qobject_dynamic_cast_assert: + * + * @obj: + * + * @typename: + * + * Returns: + * + */ +QObject *qobject_dynamic_cast_assert(QObject *obj, const char *typename); + +/** + * @qobject_is_type: + * + * @obj: + * + * @typename: + * + * Returns: + * + */ +bool qobject_is_type(QObject *obj, const char *typename); + +/** + * @qobject_get_class: + * + * @obj: + * + * Returns: + * + */ +QObjectClass *qobject_get_class(QObject *obj); + +/** + * @qobject_get_type: + * + * @obj: + * + * Returns: + */ +const char *qobject_get_type(QObject *obj); + +/** + * @qobject_get_super: + * + * @obj: + * + * Returns: + */ +QObjectClass *qobject_get_super(QObject *obj); + +/**/ + +/** + * @qtype_register_static: + * + * @info: + * + * Returns: + */ +QType qtype_register_static(const QTypeInfo *info); + +/** + * @qobject_check_class: + * + * @obj: + * + * @typename: + * + * Returns: + */ +QObjectClass *qobject_check_class(QObjectClass *obj, const char *typename); + +/** + * @qtype_get_by_name: + * + * @name: + * + * Returns: + */ +QType qtype_get_by_name(const char *name); + +/** + * @qtype_get_name: + * + * @type: + * + * Returns: + */ +const char *qtype_get_name(QType type); + +#endif