[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 2/4] qom: provide convenient macros for declaring and definin
From: |
Eduardo Habkost |
Subject: |
Re: [PATCH 2/4] qom: provide convenient macros for declaring and defining types |
Date: |
Tue, 11 Aug 2020 14:22:06 -0400 |
I've just noticed this:
On Thu, Jul 23, 2020 at 07:14:08PM +0100, Daniel P. Berrangé wrote:
> When creating new QOM types, there is a lot of boilerplate code that
> must be repeated using a standard pattern. This is tedious to write
> and liable to suffer from subtle inconsistencies. Thus it would
> benefit from some simple automation.
>
> QOM was loosely inspired by GLib's GObject, and indeed GObject suffers
> from the same burden of boilerplate code, but has long provided a set of
> macros to eliminate this burden in the source implementation. More
> recently it has also provided a set of macros to eliminate this burden
> in the header declaration.
>
> In GLib there are the G_DECLARE_* and G_DEFINE_* family of macros
> for the header declaration and source implementation respectively:
>
> https://developer.gnome.org/gobject/stable/chapter-gobject.html
> https://developer.gnome.org/gobject/stable/howto-gobject.html
>
> This patch takes inspiration from GObject to provide the equivalent
> functionality for QOM.
>
> In the header file, instead of:
>
> typedef struct MyDevice MyDevice;
> typedef struct MyDeviceClass MyDeviceClass;
>
> G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)
Isn't this supposed to be
G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDevice, object_unref)
?
>
> #define MY_DEVICE_GET_CLASS(void *obj) \
> OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
> #define MY_DEVICE_CLASS(void *klass) \
> OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
> #define MY_DEVICE(void *obj)
> OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
>
> struct MyDeviceClass {
> DeviceClass parent_class;
> };
>
> We now have
>
> OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
>
> In cases where the class needs some virtual methods, it can be left
> to be implemented manually using
>
> OBJECT_DECLARE_TYPE(MyDevice, my_device, MY_DEVICE)
>
> Note that these macros are including support for g_autoptr() for the
> object types, which is something previously only supported for variables
> declared as the base Object * type.
[...]
> + * <example>
> + * <title>Expansion from declaring a simple type</title>
> + * <programlisting>
> + * typedef struct MyDevice MyDevice;
> + * typedef struct MyDeviceClass MyDeviceClass;
> + *
> + * G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)
> + *
> + * #define MY_DEVICE_GET_CLASS(void *obj) \
> + * OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
> + * #define MY_DEVICE_CLASS(void *klass) \
> + * OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
> + * #define MY_DEVICE(void *obj)
> + * OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
> + *
> + * struct MyDeviceClass {
> + * DeviceClass parent_class;
> + * };
> + * </programlisting>
> + * </example>
[...]
> +#define OBJECT_DECLARE_TYPE(ModuleObjName, module_obj_name, MODULE_OBJ_NAME)
> \
> + typedef struct ModuleObjName ModuleObjName; \
> + typedef struct ModuleObjName##Class ModuleObjName##Class; \
> + \
> + G_DEFINE_AUTOPTR_CLEANUP_FUNC(ModuleObjName##Class, object_unref) \
> + \
> + static inline G_GNUC_UNUSED ModuleObjName##Class * \
> + MODULE_OBJ_NAME##_GET_CLASS(void *obj) \
> + { return OBJECT_GET_CLASS(ModuleObjName##Class, obj, \
> + TYPE_##MODULE_OBJ_NAME); } \
> + \
> + static inline G_GNUC_UNUSED ModuleObjName##Class * \
> + MODULE_OBJ_NAME##_CLASS(void *klass) \
> + { return OBJECT_CLASS_CHECK(ModuleObjName##Class, klass, \
> + TYPE_##MODULE_OBJ_NAME); } \
> + \
> + static inline G_GNUC_UNUSED ModuleObjName * \
> + MODULE_OBJ_NAME(void *obj) \
> + { return OBJECT_CHECK(ModuleObjName, obj, \
> + TYPE_##MODULE_OBJ_NAME); }
> +
[...]
--
Eduardo