#ifndef GLIB_UTILITY_H_INCLUDED
#define GLIB_UTILITY_H_INCLUDED
/* glib-utility.h - Utility routines that make it easier to use the
object-oriented features of GLib/GObject.
Copyright (C) 2013 Michael Malicoat.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
*/
/** \file
This file defines several macros and utility routines that make it easier
to use the object-oriented features of GLib/GObject.
*/
#include
#include
#include
#include
/// This macro makes g_class() statements easier to read
/** This macro makes `g_class()` statements easier to read, as it delimits the
instance variables from the class variables.
See the documentation for the `g_class()` macro for an example of how
this macro is used.
*/
#define g_instance(code...) code
/// Defines a class and the standard functions associated with it
/** Together with g_class_implement(), this macro removes some of the tedium
inherent in declaring a class using GLib/GObject and causes code to look
similar to a standard object-oriented language.
This macro defines:
- The class structure
- The class instance structure
- The standard type identification and casting routines for the class:
- `IS_[new type name]`,
- `[new type name]_CLASS`,
- `IS_[new type name]_CLASS`, and
- `[new type name]_GET_CLASS`
These are defined as inline functions, rather than macros, but since
they are included as part of the class header file, they are accessible
wherever the header file is accessible, and (at least in GCC), they are
as fast as macros.
- The type registration routine: `[new type name]_get_type()`
This macro expects the following parameters:
- `instName` -- The canonical name of the class; e.g., `MyClass`
- `parentInstName` -- The canonical name of the class from which the new
class descends; e.g., `AnObject` or `GObject`
- `typeName` -- The name of the class as used in the standard type
identification and casting routines; e.g., `MY_OBJECT`
- `funcPrefix` -- The prefix assigned to functions and methods associated
with this class; e.g., `my_object`
- `instCode` -- One or more lines of code that will be copied into the
instance structure for the class. This is where you will define
instance variables for the class. To make the code easy to read, you
will likely preface this section with the `g_instance()` macro.
- `...` -- One or more lines of code that will be copied into the class
structure for the class. This is where you will define class variables
and virtual methods.
Here is an example of how this macro is used. The code below defines
a class named `AnObject`, which descends from `GObject`. In its type
identification and casting routines, the class is referenced as
`AN_OBJECT`, while functions and methods related to the class are
prefixed with `an_object`. The class has one instance variable, named
`DisplayName`, and defines one virtual method: `name()`.
\code
#include "utility/glib-utility.h"
// The base class, from which nearly all others are derived
g_class(AnObject, GObject, AN_OBJECT, an_object,
g_instance(
//
// Stores the display name of the class
gpointer DisplayName;
),
// Retrieve the name of the object
def(char *)(*name)(AnObject *Self);
)
\endcode
For more information on the above, you may consult the GTK+ documentation at
http://www.gtk.org/documentation.php.
*/
#define g_class(instName, parentInstName, typeName, funcPrefix, instCode, ...) \
typedef struct instName instName; \
typedef struct instName ## Class instName ##Class; \
GType funcPrefix ## _get_type (void); \
static inline instName *typeName (gpointer inst) \
{ \
return (instName *)g_instance_cast(inst, funcPrefix ## _get_type());\
} \
\
static inline gboolean IS_ ## typeName (gpointer inst) \
{ \
return g_instance_valid(inst, funcPrefix ## _get_type()); \
} \
\
static inline instName ## Class *typeName ## _CLASS (gpointer klass) \
{ \
return (instName ## Class *) g_class_cast(klass, funcPrefix ## _get_type()); \
} \
\
static inline gboolean IS_ ## typeName ## _CLASS (gpointer klass) \
{ \
return g_class_valid(klass, funcPrefix ## _get_type()); \
} \
\
static inline instName ## Class *typeName ## _GET_CLASS (gpointer inst) \
{ \
return (instName ## Class *) g_instance_class(inst, \
funcPrefix ## _get_type()); \
} \
\
struct instName ## Class { \
parentInstName ## Class Parent; \
__VA_ARGS__ \
}; \
\
struct instName { \
parentInstName Parent; \
instCode \
};
/// This macro makes g_class_implement() statements easier to read
/** This macro makes `g_class_implement()` statements easier to read, as it
delimits the class preamble code from other code. Class preamble code
is placed _before_ the `_get_type()` function for the associated class.
*/
#define g_class_preamble(code...) code
/// This macro makes g_class_implement() statements easier to read
/** This macro makes `g_class_implement()` statements easier to read, as it
delimits the class type definition code from other code.
Class type definition code is placed in the body of the `_get_type()`
function for the associated class, after the class type is declared and
registered. This is where you will put `g_adopt()` statements, among other
things.
*/
#define g_class_typedef(code...) code
/// This macro makes g_class_implement() statements easier to read
/** This macro makes `g_class_implement()` statements easier to read , as it
delimits the class initialization code from other code.
Class initialization code is placed in the body of the `_class_init()`
function for the associated class. This code is called each time the class
object is initialized (i.e., the first time the class is used, and whenever
a descendant class object is used). This is where you will define and
override virtual methods.
*/
#define g_class_init(code...) code
/// This macro makes g_class_implement() statements easier to read
/** This macro makes `g_class_implement()` statements easier to read, as it
delimits the instance initialization code from other code.
Instance initialization code is placed in the body of the `_init()`
function for the associated class. This code is called each time an
instance of the class is created. This is where you will set the default
values of instance variables.
*/
#define g_instance_init(code...) code
/// This macro makes g_class_implement() statements easier to read
/** This macro makes `g_class_implement()` statements easier to read, as it
delimits the instance disposal code from other code.
Instance disposal code is placed in the body of the `_dispose()` function
for the associated class. This code may be called more than once. This
is where you will release references to any other reference-counted objects
(any descendants of AnObject or `GObject`).
This macro ensures that the disposal function chains up to the parent
class.
*/
#define g_instance_dispose(code...) code
/// This macro makes g_class_implement() statements easier to read
/** This macro makes `g_class_implement()` statements easier to read, as it
delimits the instance finalization code from other code.
Instance finalization code is placed in the body of the `_finalize()`
function for the associated class. This code will be called only once.
This is where you will finish releasing memory owned by the instance.
This macro ensures that the finalization function chains up to the parent
class.
*/
#define g_instance_finalize(code...) code
/// This macro is a riff on the g_return_if_fail() macros
/** This macro is a riff on the `g_return_if_fail()` macros, except it is a
little more flexible and somewhat less verbose (fewer ugly underscores).
This macro tests `expr` to see if it evaluates as #true or #FALSE; if
#FALSE, `code` is executed. `code` may be one or more lines of arbitrary
code; however, it will most often consist of a single `return` statement,
as this macro is best used at the beginning of a method to test whether
the variable that represents `Self` is the right type, and to quickly exit
the routine if not.
*/
#define g_if_fail(expr, code...) \
if ( G_UNLIKELY(!(expr) ) ) \
code
/// Extends GTypeInfo
/** This type extends GTypeInfo to allow the name of the class and a reference
to its parent type to be encoded as part of a static class definition. It
matches GTypeInfo exactly, except for the addition of several fields at the
end; this allows it to be used interchangeably with GTypeInfo.
\extends GTypeInfo
*/
typedef struct GExtendedTypeInfo {
/* interface types, classed types, instantiated types */
guint16 class_size;
GBaseInitFunc base_init;
GBaseFinalizeFunc base_finalize;
/* interface types, classed types, instantiated types */
GClassInitFunc class_init;
GClassFinalizeFunc class_finalize;
gconstpointer class_data;
/* instantiated types */
guint16 instance_size;
guint16 n_preallocs;
GInstanceInitFunc instance_init;
/* value handling */
const GTypeValueTable *value_table;
/* Additional information */
void (*instance_dispose)(GObject *This);
void (*instance_finalize)(GObject *This);
const char *class_name;
GType class_type;
gpointer parent;
} GExtendedTypeInfo;
/// Implements the standard functions associated with a class
/** Together with g_class(), this macro helps to reduce the tedium of defining
and implementing a class using GLib/GObject.
This macro defines and implements the standard functions associated with
a GLib/GObject class, namely:
- `[new type name]_class_init()`,
- `[new type name]_init()`,
- `[new type name]_dispose()`, and
- `[new type name]_finalize()`
The macro also implements the type registration function:
- `[new type name]_get_type()`
Whereas g_class() is designed for use in the header file that defines the
class, this macro is designed to be used in the source file for the class.
This macro expects several parameters:
- `instName` -- The canonical name of the class; e.g., `MyClass`
- `parentType` -- The type identifier of the parent class; e.g.,
`G_TYPE_OBJECT`, `AN_OBJECT_TYPE`
- `typeName` -- The identifier used for the class in its type identification
and casting routines; e.g., `MY_CLASS`
- `preambleCode` -- One or more lines of code that will be placed in the
code before the type registration function. This is where you will
define global variables related to the class, if any. To make the code
easier to read, you will likely wrap this section with
`g_class_preamble()`.
- `typedefCode` -- One or more lines of code that will be placed in the
body of the type registration function (`[new type name]_get_type()`).
This is where you will declare interfaces that are implemented by the
class. To make the code easier to read, you will likely wrap this
section with `g_class_typedef()`.
- `constructCode` -- One or more lines of code that will be placed in the
body of the class constructor function (`[new type name]_class_init()`).
This is where you will initialize and override virtual methods. To
make the code easier to read, you will likely wrap this section with
`g_class_init()`.
- 'initCode` -- One or more lines of code that will be placed in the body
of the instance constructor function (`[new type name]_init()`). This is
where you will initialize instance variables. To make the code easier
to read, you will likely wrap this section with `g_instance_init()`.
- 'destructCode` -- One or more lines of code that will be placed in the
body of the instance disposal function (`[new type name]_dispose()`).
This is where you will free any references that the instance holds to
other reference-counted objects. To make the code easier to read, you
will likely wrap this section with `g_instance_dispose()`.
- `finalCode` -- One or more lines of code that will be placed in the body
of the instance finalization function (`[new type name]_finalize()`).
This is where you will finish releasing any resources held by the
instance. To make the code easier to read, you will likely wrap this
section with `g_instance_finalize()`.
Below is an example of how this macro is used for the class defined in
the example code shown for g_class(). The class implements no interfaces,
so the `g_class_typedef()` section remains empty. It establishes the
base implementation of its one virtual method in the class constructor
function, and initializes its only instance variable in the instance
initialization function. Finally, it frees that instance variable in
the disposal function, checking to ensure that it was not already freed,
since the function may be called more than once.
\code
g_class_implement(AnObject, G_TYPE_OBJECT, AN_OBJECT, an_object,
g_class_preamble(),
g_class_typedef(),
g_class_init(
// Establish virtual methods
Self->name = an_object_display_name;
),
g_instance_init(
// Establish private attributes
Self->DisplayName = NULL;
),
g_instance_dispose(
// Free the display name
if ( Self->DisplayName != NULL ) {
g_object_unref(Self->DisplayName);
Self->DisplayName = NULL;
}
),
g_instance_finalize()
)
\endcode
*/
#define g_class_implement(instName, parentType, typeName, funcPrefix, preambleCode, typedefCode, constructCode, initCode, destructCode, finalCode) \
static void funcPrefix ## _class_init (instName ## Class *Self); \
static void funcPrefix ## _init (instName *Self); \
static void funcPrefix ## _dispose (GObject *This); \
static void funcPrefix ## _finalize (GObject *This); \
\
static GExtendedTypeInfo funcPrefix ## _definition = { \
sizeof(instName ## Class), \
NULL, \
NULL, \
(GClassInitFunc)(funcPrefix ## _class_init), \
NULL, \
NULL, \
sizeof(instName), \
0, \
(GInstanceInitFunc)(funcPrefix ## _init), \
NULL, \
funcPrefix ## _dispose, \
funcPrefix ## _finalize, \
#instName, \
0, \
NULL \
}; \
\
preambleCode \
\
GType funcPrefix ## _get_type (void) \
{ \
if ( funcPrefix ## _definition.class_type != 0 ) \
return funcPrefix ## _definition.class_type; \
\
funcPrefix ## _definition.class_type = g_type_register_static(parentType, \
funcPrefix ## _definition.class_name, \
(GTypeInfo *)(&funcPrefix ## _definition), 0); \
typedefCode \
return funcPrefix ## _definition.class_type; \
} \
\
static void funcPrefix ## _class_init(instName ## Class *Self) \
{ \
GObjectClass *Base = G_OBJECT_CLASS(Self); \
Base->dispose = funcPrefix ## _definition.instance_dispose; \
Base->finalize = funcPrefix ## _definition.instance_finalize; \
funcPrefix ## _definition.parent = g_type_class_peek_parent(Self); \
constructCode \
} \
\
static void funcPrefix ## _init(instName *Self) \
{ \
initCode \
}\
\
static void funcPrefix ## _dispose(GObject *This) \
{ \
instName *Self = typeName(This); \
destructCode \
G_OBJECT_CLASS(funcPrefix ## _definition.parent)->dispose(This); \
} \
\
static void funcPrefix ## _finalize(GObject *This) \
{ \
instName *Self = typeName(This); \
finalCode \
G_OBJECT_CLASS(funcPrefix ## _definition.parent)->finalize(This); \
}
/// Returns a reference to the specified parent class of the given instance
#define G_INSTANCE_GET_SUPER_CLASS(inst, parentTypeName, parentInstName) \
((parentInstName ## Class *)\
(g_type_class_peek_parent(parentTypeName ## _GET_CLASS (inst))))
/// Returns a reference to the specified parent class for 'Self'
#define inherited(parentTypeName, parentInstName) \
G_INSTANCE_GET_SUPER_CLASS(Self, parentTypeName, parentInstName)
/// Returns a reference to the specified parent interface implementation
#define G_INSTANCE_GET_SUPER_INTERFACE(inst, parentTypeName, parentInstName) \
(parentTypeName ## Interface *) \
(g_type_interface_peek_parent(parentTypeName ## _GET_INTERFACE (inst))
/// Returns a reference to the specified parent interface for 'Self'
#define iinherited(parentTypeName, parentInstName) \
G_INSTANCE_GET_SUPER_INTERFACE(Self, parentTypeName, parentInstName)
/// Registers the adoption of an interface
#define g_adopt(iface, ifaceType, funcPrefix) \
static const GInterfaceInfo funcPrefix ## _ ## iface ## _implementation = { \
(GInterfaceInitFunc)(funcPrefix ## _implement_ ## iface), \
NULL, \
NULL \
}; \
\
g_type_add_interface_static(funcPrefix ## _definition.class_type, \
ifaceType ## _INTERFACE, \
&funcPrefix ## _ ## iface ## _implementation)
/// Performs standard initialization of an interface registrar
#define g_class_interface(iface, funcPrefix, code...) \
static void funcPrefix ## _implement_ ## iface(iface ## Interface *Interface) \
{ \
code \
}
/// Constructs a new instance of the specified class without construction parameters
#define g_instance_new(type) (g_object_new(type, NULL))
/// Frees a reference to the specified instance
#define g_instance_free(inst) (g_object_unref(inst))
/// Casts the specified instance to the specified type
static inline gpointer g_instance_cast(gpointer inst, GType type)
{
return G_TYPE_CHECK_INSTANCE_CAST(inst, type, gpointer);
}
#ifdef _DEBUG_
// Useful for debugging output
#if __STDC_VERSION__ < 199901L
#if __GNUC__ >= 2
#define __func__ __FUNCTION__
#else
#define __func__ ""
#endif
#endif
// Useful for debugging output
static const char *errTypeCheck = "%s:%lld: invalid \"%s\" instance passed "
"to function %s()";
#define g_instance_valid(inst, type) \
(g_instance_valid_debug(inst, type, __FILE__, __LINE__, __func__))
/// Determines if the specified instance is of the specified type
static gboolean g_instance_valid_debug(gpointer inst,
GType type, const gchar *source, gint64 line, const gchar *func)
{
// Stores the result of the test
gboolean result = FALSE;
if ( inst != NULL )
result = G_TYPE_CHECK_INSTANCE_TYPE(inst, type);
if ( result == FALSE )
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
errTypeCheck, source, line, g_type_name(type), func
);
return result;
}
#define g_class_valid(klass, type) \
(g_class_valid_debug(klass, type, __FILE__, __LINE__, __func__))
/// Determines if the specified class is of the specified type
static gboolean g_class_valid_debug(gpointer klass, GType type,
const gchar *source, gint64 line, const gchar *func)
{
// Stores the result of the test
gboolean result = FALSE;
if (klass != NULL)
result = G_TYPE_CHECK_CLASS_TYPE(klass, type);
if (result == FALSE)
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
errTypeCheck, source, line, g_type_name(type), func
);
return result;
}
#else
/// Determines if the specified instance is of the specified type
static inline gboolean g_instance_valid(gpointer inst, GType type)
{
return G_TYPE_CHECK_INSTANCE_TYPE(inst, type);
}
/// Determines if the specified class is of the specified type
static inline gboolean g_class_valid(gpointer klass, GType type)
{
return G_TYPE_CHECK_CLASS_TYPE(klass, type);
}
#endif
/// Casts the specified class to the specified type
static inline gpointer g_class_cast(gpointer klass, GType type)
{
return G_TYPE_CHECK_CLASS_CAST(klass, type, gpointer);
}
/// Obtains the parent of the specified instance
static inline gpointer g_instance_class(gpointer inst, GType type)
{
return G_TYPE_INSTANCE_GET_CLASS(inst, GType, gpointer);
}
/// Obtains a reference to the specified interface
static inline gpointer g_instance_interface(gpointer inst, GType type)
{
return G_TYPE_INSTANCE_GET_INTERFACE(inst, type, gpointer);
}
/// Gets the value of a boolean property from the specified instance
static inline gboolean g_object_get_boolean(gpointer inst,
const char *name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gboolean result = FALSE;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_BOOLEAN);
g_object_get_property(inst, name, &value);
result = g_value_get_boolean(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a short integer property from the specified instance
static inline gint8 g_object_get_char(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gint8 result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_CHAR);
g_object_get_property(inst, name, &value);
result = g_value_get_char(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a byte property from the specified instance
static inline guchar g_object_get_uchar(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
guchar result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_UCHAR);
g_object_get_property(inst, name, &value);
result = g_value_get_uchar(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a signed integer property from the specified instance
static inline gint g_object_get_int(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gint result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_INT);
g_object_get_property(inst, name, &value);
result = g_value_get_int(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of an unsigned integer property from the specified instance
static inline guint g_object_get_uint(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
guint result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_UINT);
g_object_get_property(inst, name, &value);
result = g_value_get_uint(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a signed long integer property from the specified instance
static inline glong g_object_get_long(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
glong result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_LONG);
g_object_get_property(inst, name, &value);
result = g_value_get_long(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of an unsigned long integer property from an instance
static inline gulong g_object_get_ulong(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gulong result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_ULONG);
g_object_get_property(inst, name, &value);
result = g_value_get_ulong(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a signed 64-bit integer property from an instance
static inline gint64 g_object_get_int64(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gint64 result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_INT64);
g_object_get_property(inst, name, &value);
result = g_value_get_int64(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of an unsigned 64-bit integer property from an instance
static inline guint64 g_object_get_uint64(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
guint64 result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_UINT64);
g_object_get_property(inst, name, &value);
result = g_value_get_uint64(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a floating-point property from the specified instance
static inline gfloat g_object_get_float(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
gfloat result = 0.0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_FLOAT);
g_object_get_property(inst, name, &value);
result = g_value_get_float(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a floating-point property from the specified instance
static inline gdouble g_object_get_double(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gdouble result = 0.0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_DOUBLE);
g_object_get_property(inst, name, &value);
result = g_value_get_double(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of an enumerated property from the specified instance
static inline gint g_object_get_enum(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gint result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_ENUM);
g_object_get_property(inst, name, &value);
result = g_value_get_enum(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a flag property from the specified instance
static inline guint g_object_get_flags(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
guint result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_FLAGS);
g_object_get_property(inst, name, &value);
result = g_value_get_flags(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a single const char * property from the specified instance
static inline const char *g_object_get_string(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Refers to the text of the const char *
const gchar *result = NULL;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_STRING);
g_object_get_property(inst, name, &value);
result = g_value_get_string(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a GParamSpec property from the specified instance
static inline GParamSpec *g_object_get_param(gpointer inst,
const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Refers to the result
GParamSpec *result = NULL;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_PARAM);
g_object_get_property(inst, name, &value);
result = g_value_get_param(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a boxed property from the specified instance
static inline gpointer g_object_get_boxed(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gpointer result = NULL;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_BOXED);
g_object_get_property(inst, name, &value);
result = g_value_get_boxed(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a pointer property from the specified instance
static inline gpointer g_object_get_pointer(gpointer inst,
const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gpointer result = NULL;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_POINTER);
g_object_get_property(inst, name, &value);
result = g_value_get_pointer(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of an object instance property from the specified instance
static inline gpointer g_object_get_object(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
gpointer result = NULL;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_OBJECT);
g_object_get_property(inst, name, &value);
result = g_value_get_object(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a GType property from the specified instance
static inline GType g_object_get_gtype(gpointer inst, const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
GType result = 0;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_GTYPE);
g_object_get_property(inst, name, &value);
result = g_value_get_gtype(&value);
g_value_unset(&value);
}
return result;
}
/// Gets the value of a GVariant property from the specified instance
static inline GVariant *g_object_get_variant(gpointer inst,
const char * name)
{
// Refers to the value of the specified property
GValue value = {0, };
// Stores the result
GVariant *result = NULL;
if ( (inst != NULL) && (name != NULL) )
{
g_value_init(&value, G_TYPE_VARIANT);
g_object_get_property(inst, name, &value);
result = g_value_get_variant(&value);
g_value_unset(&value);
}
return result;
}
/// Raises a GError
static inline void g_raise(GError **err, GQuark domain, gint code,
const char * fmt, ...)
{
// Stores the resulting message
char *msg = NULL;
// Stores the list of arguments passed to the routine
va_list args;
if ( (*err == NULL) && (fmt != NULL) ) {
va_start(args, fmt);
g_vasprintf(&msg, fmt, args);
va_end(args);
g_set_error_literal(err, domain, code, msg);
g_free(msg);
}
}
/// Defines an interface and the standard functions associated with it
#define g_interface(ifaceName, parentInstName, typeName, funcPrefix, code...) \
typedef struct ifaceName ifaceName; \
typedef struct ifaceName ## Interface ifaceName ## Interface; \
GType funcPrefix ## _get_type(void); \
inline ifaceName *typeName (gpointer inst); \
inline gboolean IS_ ## typeName (gpointer inst); \
inline ifaceName ## Interface *typeName ##_GET_INTERFACE (gpointer inst); \
\
struct ifaceName {}; \
struct ifaceName ## Interface { \
parentInstName ## Interface Parent; \
code \
};
/// Implements standard functions for an interface
#define g_interface_implement(ifaceName, parentType, typeName, funcPrefix, code...) \
static void funcPrefix ## _base_init(ifaceName ## Interface *Self); \
\
static GExtendedTypeInfo funcPrefix ## _definition = { \
sizeof(ifaceName ## Interface), \
(GBaseInitFunc)(funcPrefix ## _base_init), \
NULL, \
NULL, \
NULL, \
NULL, \
sizeof(ifaceName), \
0, \
NULL, \
NULL, \
NULL, \
NULL, \
#ifaceName, \
0, \
NULL \
}; \
\
GType funcPrefix ## _get_type(void) \
{ \
if ( funcPrefix ## _definition.class_type != 0 ) \
return funcPrefix ## _definition.class_type; \
\
funcPrefix ## _definition.class_type = g_type_register_static(parentType, \
funcPrefix ## _definition.class_name, \
(GTypeInfo *)(&funcPrefix ## _definition), 0); \
return funcPrefix ## _definition.class_type; \
} \
\
inline ifaceName *typeName (gpointer inst) { \
return (ifaceName *)(g_instance_cast(inst, funcPrefix ## _get_type())); \
} \
\
inline gboolean IS_ ## typeName (gpointer inst) { \
return g_instance_valid(inst, funcPrefix ## _get_type()); \
} \
\
inline ifaceName ## Interface *typeName ##_GET_INTERFACE (gpointer inst) { \
return (ifaceName ## Interface *)\
g_instance_interface(inst, funcPrefix ## _get_type()); \
}\
static void funcPrefix ## _base_init(ifaceName ## Interface *Self) \
{ \
static gboolean initialized = FALSE; \
if ( initialized ) \
return; \
initialized = TRUE; \
code \
}
/// This macro makes g_interface_implement() statements easier to read, as it
/// delimits the base initialization code from other code.
#define g_interface_init(code...) code
/// Defines functions that will be exported (for callbacks via GModule, among other things)
#ifdef __CYGWIN__
#define export(t) G_MODULE_EXPORT t
#else
#define export(t) t
#endif
#endif // GLIB_UTILITY_H_INCLUDED