From patchwork Tue Dec 20 16:51:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Liguori X-Patchwork-Id: 132465 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 178AEB702F for ; Wed, 21 Dec 2011 04:27:30 +1100 (EST) Received: from localhost ([::1]:39161 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rd2wA-0007rW-Q3 for incoming@patchwork.ozlabs.org; Tue, 20 Dec 2011 11:53:10 -0500 Received: from eggs.gnu.org ([140.186.70.92]:35295) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rd2vB-00055l-4d for qemu-devel@nongnu.org; Tue, 20 Dec 2011 11:52:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Rd2v4-0006Rv-6K for qemu-devel@nongnu.org; Tue, 20 Dec 2011 11:52:09 -0500 Received: from cpe-70-123-132-139.austin.res.rr.com ([70.123.132.139]:41589 helo=localhost6.localdomain6) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rd2v3-0006Rp-QM for qemu-devel@nongnu.org; Tue, 20 Dec 2011 11:52:02 -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 pBKGpxZx021408; Tue, 20 Dec 2011 10:51:59 -0600 Received: (from anthony@localhost) by localhost6.localdomain6 (8.14.4/8.14.4/Submit) id pBKGpwe5021405; Tue, 20 Dec 2011 10:51:58 -0600 From: Anthony Liguori To: qemu-devel@nongnu.org Date: Tue, 20 Dec 2011 10:51:30 -0600 Message-Id: <1324399916-21315-2-git-send-email-aliguori@us.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1324399916-21315-1-git-send-email-aliguori@us.ibm.com> References: <1324399916-21315-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: Paolo Bonzini , Anthony Liguori , Markus Armbruster Subject: [Qemu-devel] [PATCH 01/27] qom: add the base Object class 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 This class provides the main building block for QEMU Object Model and is extensively documented in the header file. It is largely inspired by GObject. Signed-off-by: Anthony Liguori --- Makefile.objs | 2 + hw/object.c | 469 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/object.h | 427 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 898 insertions(+), 0 deletions(-) create mode 100644 hw/object.c create mode 100644 hw/object.h diff --git a/Makefile.objs b/Makefile.objs index f753d83..b86e8a1 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -122,6 +122,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 += object.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/object.c b/hw/object.c new file mode 100644 index 0000000..620e63f --- /dev/null +++ b/hw/object.c @@ -0,0 +1,469 @@ +/* + * 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 "object.h" + +#define MAX_INTERFACES 32 + +typedef struct InterfaceImpl +{ + const char *parent; + void (*interface_initfn)(ObjectClass *class, void *data); + Type type; +} InterfaceImpl; + +typedef struct TypeImpl +{ + const char *name; + Type type; + + size_t class_size; + + size_t instance_size; + + void (*base_init)(ObjectClass *klass); + void (*base_finalize)(ObjectClass *klass); + + void (*class_init)(ObjectClass *klass, void *data); + void (*class_finalize)(ObjectClass *klass, void *data); + + void *class_data; + + void (*instance_init)(Object *obj); + void (*instance_finalize)(Object *obj); + + bool abstract; + + const char *parent; + + ObjectClass *class; + + int num_interfaces; + InterfaceImpl interfaces[MAX_INTERFACES]; +} TypeImpl; + +static int num_types = 1; +static TypeImpl type_table[1024]; + +Type type_register_static(const TypeInfo *info) +{ + Type type = num_types++; + TypeImpl *ti; + + ti = &type_table[type]; + + assert(info->name != NULL); + + printf("Added type %s -> %s\n", info->name, info->parent); + + 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->class_data = info->class_data; + + 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 Type type_register_anonymous(const TypeInfo *info) +{ + Type type = num_types++; + TypeImpl *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->class_data = info->class_data; + + 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 TypeImpl *type_get_instance(Type type) +{ + assert(type != 0); + assert(type < num_types); + + return &type_table[type]; +} + +static Type type_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 type_class_base_init(TypeImpl *base_ti, const char *typename) +{ + TypeImpl *ti; + + if (!typename) { + return; + } + + ti = type_get_instance(type_get_by_name(typename)); + + type_class_base_init(base_ti, ti->parent); + + if (ti->base_init) { + ti->base_init(base_ti->class); + } +} + +static size_t type_class_get_size(TypeImpl *ti) +{ + if (ti->class_size) { + return ti->class_size; + } + + if (ti->parent) { + return type_class_get_size(type_get_instance(type_get_by_name(ti->parent))); + } + + return sizeof(ObjectClass); +} + +static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface) +{ + TypeInfo info = { + .instance_size = sizeof(Interface), + .parent = iface->parent, + .class_size = sizeof(InterfaceClass), + .class_init = iface->interface_initfn, + .abstract = true, + }; + + iface->type = type_register_anonymous(&info); +} + +static void type_class_init(TypeImpl *ti) +{ + size_t class_size = sizeof(ObjectClass); + int i; + + if (ti->class) { + return; + } + + ti->class_size = type_class_get_size(ti); + + ti->class = g_malloc0(ti->class_size); + ti->class->type = ti->type; + + if (ti->parent) { + TypeImpl *ti_parent; + + ti_parent = type_get_instance(type_get_by_name(ti->parent)); + + type_class_init(ti_parent); + + class_size = ti_parent->class_size; + assert(ti_parent->class_size <= ti->class_size); + + memcpy((void *)ti->class + sizeof(ObjectClass), + (void *)ti_parent->class + sizeof(ObjectClass), + ti_parent->class_size - sizeof(ObjectClass)); + } + + memset((void *)ti->class + class_size, 0, ti->class_size - class_size); + + type_class_base_init(ti, ti->parent); + + for (i = 0; i < ti->num_interfaces; i++) { + type_class_interface_init(ti, &ti->interfaces[i]); + } + + if (ti->class_init) { + ti->class_init(ti->class, ti->class_data); + } +} + +static void object_interface_init(Object *obj, InterfaceImpl *iface) +{ + TypeImpl *ti = type_get_instance(iface->type); + Interface *iface_obj; + + iface_obj = INTERFACE(object_new(ti->name)); + iface_obj->obj = obj; + + obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj); +} + +static void object_init(Object *obj, const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + int i; + + if (ti->parent) { + object_init(obj, ti->parent); + } + + for (i = 0; i < ti->num_interfaces; i++) { + object_interface_init(obj, &ti->interfaces[i]); + } + + if (ti->instance_init) { + ti->instance_init(obj); + } +} + +void object_initialize(void *data, const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + Object *obj = data; + + g_assert(ti->instance_size >= sizeof(ObjectClass)); + + type_class_init(ti); + + g_assert(ti->abstract == false); + + memset(obj, 0, ti->instance_size); + + obj->class = ti->class; + + object_init(obj, typename); +} + +static void object_deinit(Object *obj, const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + + if (ti->instance_finalize) { + ti->instance_finalize(obj); + } + + while (obj->interfaces) { + Interface *iface_obj = obj->interfaces->data; + obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces); + object_delete(OBJECT(iface_obj)); + } + + if (ti->parent) { + object_init(obj, ti->parent); + } +} + +void object_finalize(void *data) +{ + Object *obj = data; + TypeImpl *ti = type_get_instance(obj->class->type); + + object_deinit(obj, ti->name); +} + +static const char *type_get_name(Type type) +{ + TypeImpl *ti = type_get_instance(type); + return ti->name; +} + +Object *object_new(const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + Object *obj; + + obj = g_malloc(ti->instance_size); + object_initialize(obj, typename); + + return obj; +} + +void object_delete(Object *obj) +{ + object_finalize(obj); + g_free(obj); +} + +static bool object_is_type(Object *obj, const char *typename) +{ + Type target_type = type_get_by_name(typename); + Type type = obj->class->type; + GSList *i; + + /* Check if typename is a direct ancestor of type */ + while (type) { + TypeImpl *ti = type_get_instance(type); + + if (ti->type == target_type) { + return true; + } + + type = type_get_by_name(ti->parent); + } + + /* Check if obj has an interface of typename */ + for (i = obj->interfaces; i; i = i->next) { + Interface *iface = i->data; + + if (object_is_type(OBJECT(iface), typename)) { + return true; + } + } + + return false; +} + +Object *object_dynamic_cast(Object *obj, const char *typename) +{ + GSList *i; + + /* Check if typename is a direct ancestor */ + if (object_is_type(obj, typename)) { + return obj; + } + + /* Check if obj has an interface of typename */ + for (i = obj->interfaces; i; i = i->next) { + Interface *iface = i->data; + + if (object_is_type(OBJECT(iface), typename)) { + return OBJECT(iface); + } + } + + /* Check if obj is an interface and it's containing object is a direct ancestor of typename */ + if (object_is_type(obj, TYPE_INTERFACE)) { + Interface *iface = INTERFACE(obj); + + if (object_is_type(iface->obj, typename)) { + return iface->obj; + } + } + + return NULL; +} + + +static void register_interface(void) +{ + static TypeInfo interface_info = { + .name = TYPE_INTERFACE, + .instance_size = sizeof(Interface), + .abstract = true, + }; + + type_register_static(&interface_info); +} + +device_init(register_interface); + +Object *object_dynamic_cast_assert(Object *obj, const char *typename) +{ + Object *inst; + + inst = object_dynamic_cast(obj, typename); + + if (!inst) { + fprintf(stderr, "Object %p is not an instance of type %s\n", obj, typename); + abort(); + } + + return inst; +} + +ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, + const char *typename) +{ + Type target_type = type_get_by_name(typename); + Type type = class->type; + + while (type) { + TypeImpl *ti = type_get_instance(type); + + if (ti->type == target_type) { + return class; + } + + type = type_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 *object_get_type(Object *obj) +{ + return type_get_name(obj->class->type); +} + +ObjectClass *object_get_class(Object *obj) +{ + return obj->class; +} + +const char *object_class_get_name(ObjectClass *klass) +{ + return type_get_name(klass->type); +} diff --git a/hw/object.h b/hw/object.h new file mode 100644 index 0000000..80b7099 --- /dev/null +++ b/hw/object.h @@ -0,0 +1,427 @@ +/* + * 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 QEMU_OBJECT_H +#define QEMU_OBJECT_H + +#include "qemu-common.h" + +typedef uint64_t Type; + +typedef struct ObjectClass ObjectClass; +typedef struct Object Object; + +typedef struct TypeInfo TypeInfo; + +typedef struct InterfaceClass InterfaceClass; +typedef struct Interface Interface; +typedef struct InterfaceInfo InterfaceInfo; + +#define TYPE_OBJECT NULL + +/** + * SECTION:object.h + * @title:Base Object Type System + * @short_description: interfaces for creating new types and objects + * + * The QEMU Object Model provides a framework for registering user creatable + * types and instantiating objects from those types. QOM provides the following + * features: + * + * - System for dynamically registering types + * - Support for single-inheritance of types + * - Multiple inheritance of stateless interfaces + * + * + * Creating a minimal type + * + * #include "qdev.h" + * + * #define TYPE_MY_DEVICE "my-device" + * + * typedef struct MyDevice + * { + * DeviceState parent; + * + * int reg0, reg1, reg2; + * } MyDevice; + * + * static TypeInfo my_device_info = { + * .name = TYPE_MY_DEVICE, + * .parent = TYPE_DEVICE, + * .instance_size = sizeof(MyDevice), + * }; + * + * static void my_device_module_init(void) + * { + * type_register_static(&my_device_info); + * } + * + * device_init(my_device_module_init); + * + * + * + * In the above example, we create a simple type that is described by #TypeInfo. + * #TypeInfo describes information about the type including what it inherits + * from, the instance and class size, and constructor/destructor hooks. + * + * Every type has an #ObjectClass associated with it. #ObjectClass derivatives + * are instantiated dynamically but there is only ever one instance for any + * given type. The #ObjectClass typically holds a table of function pointers + * for the virtual methods implemented by this type. + * + * Using object_new(), a new #Object derivative will be instantiated. You can + * cast an #Object to a subclass (or base-class) type using + * object_dynamic_cast(). You typically want to define a macro wrapper around + * object_dynamic_cast_assert() to make it easier to convert to a specific type. + * + * # 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, #TypeInfo::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. #TypeInfo::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 + * #TypeInfo::base_init functions have been called, #TypeInfo::class_init is + * called to let the class being instantiated provide default initialize for + * it's virtual functions. + * + * # Interfaces # + * + * Interfaces 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 #Interface types and vice versa. + */ + +/** + * ObjectClass: + * + * The base for all classes. The only thing that #ObjectClass contains is an + * integer type handle. + */ +struct ObjectClass +{ + /*< private >*/ + Type type; +}; + +/** + * Object: + * + * The base for all objects. The first member of this object is a pointer to + * a #ObjectClass. 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 #Object. + * + * As a result, #Object contains a reference to the objects type as its + * first member. This allows identification of the real type of the object at + * run time. + * + * #Object also contains a list of #Interfaces that this object + * implements. + */ +struct Object +{ + /*< private >*/ + ObjectClass *class; + + GSList *interfaces; +}; + +/** + * TypeInfo: + * @name: The name of the type. + * @parent: The name of the parent type. + * @instance_size: The size of the object (derivative of #Object). If + * @instance_size is 0, then the size of the object will be the size of the + * parent object. + * @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. + * @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. + * @abstract: If this field is true, then the class is considered abstract and + * cannot be directly instantiated. + * @class_size: The size of the class object (derivative of #ObjectClass) + * 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. + * @base_init: This function is called after memcpy()'ing the base class into + * the new class to reinitialize any members that require deep copy. + * @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. + * @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. + * @class_finalize: This function is called during class destruction and is + * meant to release and dynamic parameters allocated by @class_init. + * @class_data: Data to pass to the @class_init and @class_finalize functions. + * This can be useful when building dynamic classes. + * @interfaces: The list of interfaces associated with this type. This + * should point to a static array that's terminated with a zero filled + * element. + */ +struct TypeInfo +{ + const char *name; + const char *parent; + + size_t instance_size; + void (*instance_init)(Object *obj); + void (*instance_finalize)(Object *obj); + + bool abstract; + size_t class_size; + + void (*base_init)(ObjectClass *klass); + void (*base_finalize)(ObjectClass *klass); + + void (*class_init)(ObjectClass *klass, void *data); + void (*class_finalize)(ObjectClass *klass, void *data); + void *class_data; + + InterfaceInfo *interfaces; +}; + +/** + * OBJECT: + * @obj: A derivative of #Object + * + * Converts an object to a #Object. Since all objects are #Objects, + * this function will always succeed. + */ +#define OBJECT(obj) \ + ((Object *)(obj)) + +/** + * OBJECT_CHECK: + * @type: The C type to use for the return value. + * @obj: A derivative of @type to cast. + * @name: The QOM typename of @type + * + * A type safe version of @object_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 OBJECT_CHECK(type, obj, name) \ + ((type *)object_dynamic_cast_assert((Object *)(obj), (name))) + +/** + * OBJECT_CLASS_CHECK: + * @class: The C type to use for the return value. + * @obj: A derivative of @type to cast. + * @name: the QOM typename of @class. + * + * A type safe version of @object_check_class. This macro is typically wrapped + * by each type to perform type safe casts of a class to a specific class type. + */ +#define OBJECT_CLASS_CHECK(class, obj, name) \ + ((class *)object_class_dynamic_cast_assert((ObjectClass *)(obj), (name))) + +/** + * OBJECT_GET_CLASS: + * @class: The C type to use for the return value. + * @obj: The object to obtain the class for. + * @name: The QOM typename of @obj. + * + * 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 OBJECT_GET_CLASS(class, obj, name) \ + OBJECT_CLASS_CHECK(class, object_get_class(OBJECT(obj)), name) + +/** + * Interface: + * @parent: The base class. + * + * The base for all Interfaces. This is a subclass of Object. Subclasses + * of #Interface should never have an instance that contains anything other + * than a single #Interface member. Do not attempt to create a type directly + * by deriving from #Interface. Use #TypeInfo::interfaces instead. + */ +struct Interface +{ + Object parent; + + /*< private >*/ + + Object *obj; +}; + +/** + * InterfaceClass: + * @parent_class: the base class + * + * The class for all interfaces. Subclasses of this class should only add + * virtual methods. + */ +struct InterfaceClass +{ + ObjectClass parent_class; +}; + +/** + * InterfaceInfo: + * @type: The name of the interface. + * @interface_initfn: This method 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. + * + * The information associated with an interface. + */ +struct InterfaceInfo +{ + const char *type; + + void (*interface_initfn)(ObjectClass *class, void *data); +}; + +#define TYPE_INTERFACE "interface" + +/** + * INTERFACE: + * @obj: the object to cast to an Interface + * + * Type safe macro to cast to #Interface + */ +#define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE) + +/** + * object_new: + * @typename: The name of the type of the object to instantiate. + * + * This function will initialize a new object using heap allocated memory. This + * function should be paired with object_delete() to free the resources + * associated with the object. + * + * Returns: The newly allocated and instantiated object. + */ +Object *object_new(const char *typename); + +/** + * object_delete: + * @obj: The object to free. + * + * Finalize an object and then free the memory associated with it. This should + * be paired with object_new() to free the resources associated with an object. + */ +void object_delete(Object *obj); + +/** + * object_initialize: + * @obj: A pointer to the memory to be used for the object. + * @typename: The name of the type of the object to instantiate. + * + * This function will initialize an object. The memory for the object should + * have already been allocated. + */ +void object_initialize(void *obj, const char *typename); + +/** + * object_finalize: + * @obj: The object to finalize. + * + * This function destroys and object without freeing the memory associated with + * it. + */ +void object_finalize(void *obj); + +/** + * object_dynamic_cast: + * @obj: The object to cast. + * @typename: The @typename to cast to. + * + * This function will determine if @obj is-a @typename. @obj can refer to an + * object or an interface associated with an object. + * + * Returns: This function returns @obj on success or #NULL on failure. + */ +Object *object_dynamic_cast(Object *obj, const char *typename); + +/** + * @object_dynamic_cast_assert: + * + * See object_dynamic_cast() for a description of the parameters of this + * function. The only difference in behavior is that this function asserts + * instead of returning #NULL on failure. + */ +Object *object_dynamic_cast_assert(Object *obj, const char *typename); + +/** + * object_get_class: + * @obj: A derivative of #Object + * + * Returns: The #ObjectClass of the type associated with @obj. + */ +ObjectClass *object_get_class(Object *obj); + +/** + * object_get_type: + * @obj: A derivative of #Object. + * + * Returns: The QOM typename of @obj. + */ +const char *object_get_type(Object *obj); + +/** + * type_register_static: + * @info: The #TypeInfo of the new type + * + * Returns: 0 on failure, the new #Type on success. + */ +Type type_register_static(const TypeInfo *info); + +/** + * object_class_dynamic_cast_assert: + * @klass: The #ObjectClass to attempt to cast. + * @typename: The QOM typename of the class to cast to. + * + * Returns: This function always returns @klass and asserts on failure. + */ +ObjectClass *object_class_dynamic_cast_assert(ObjectClass *klass, + const char *typename); + +/** + * object_class_get_name: + * @klass: The class to obtain the QOM typename for. + * + * Returns: The QOM typename for @klass. + */ +const char *object_class_get_name(ObjectClass *klass); + +#endif