GObject Basic Concepts
A brief tutorial on how to write a GObject
Overview
GObject provides object types, inheritance, properties, and virtual methods for C APIs and language bindings. See: GObject Manual, GObject Wikipedia.
Namespaces
The library is divided in two main name-spaces, Ncm (NumCosmoMath) where all generic mathematical and statistical objects and functions are defined, Nc (NumCosmo) where all cosmological related objects and functions are defined. All types must be labeled using the camel-case, and start with the respective name-space. For example, NcmSpline is the type used to store instances of the Spline object which lives in the NumCosmoMath name-space. Similarly, NcHICosmo is the type used for the abstract object defining homogeneous and isotropic models (HICosmo).
Methods, functions and other names
Functions and methods must be lower case and the terms separated by underscores, that is, a method of NcmSpline must be called ncm_spline_method_name. It is acceptable for the method_name to have upper case letters when necessary. For example, nc_hicosmo_Omega_m0 uses the capital Omega to avoid confusion with lowercase omega_m0, which has a different meaning in the cosmological literature.
Macros, enumerator and flags labels should be in uppercase and separated by underscores. See for example NcHICosmoImpl for a flag type. The flag type itself, NcHICosmoImpl, must be in camel-case but its labels are underscore separated uppercase.
A full example of a GObject implementation inside NumCosmo is the NcmModel class description.
Object implementation
An object named NcObjectName implements:
nc_object_name_class_init: define methods and properties. Called once per class.nc_object_name_init: initialize each instance, including private members that are not properties. Members of a type such asNcmModelCtrlare initialized here rather than through a property._nc_object_name_set_property/_get_property: handle property assignment. Every property declaredG_PARAM_CONSTRUCTorG_PARAM_CONSTRUCT_ONLYis set during construction, using the value passed tonc_object_name_newor the default if none was passed. Construct-only properties cannot change afterwards. A property that is neither is set only when explicitly passed; its declared default is never applied._nc_object_name_constructed: perform work that requires constructed property values._nc_object_name_dispose: release object references with_clearfunctions. It may run more than once, since GObject calls it repeatedly to break reference cycles, which is why every release here must use_clear. See the GObject memory management documentation._nc_object_name_finish: release memory not managed by GObject.
Default methods
In NumCosmo we have the following conventions for methods that all objects must implement:
nc_object_name_ref: incrementref_count.nc_object_name_clear/_free: decrementref_count. The_clearvariant also acceptsNULLand sets the pointer toNULL.
Example
See below a simple example of NumCosmo/GObject implementation.
Header for NcObjectName
#ifndef _NC_OBJECT_NAME_H_
#define _NC_OBJECT_NAME_H_
#include <glib.h>
#include <glib-object.h>
G_BEGIN_DECLS
#define NC_TYPE_OBJECT_NAME (nc_object_name_get_type())
G_DECLARE_FINAL_TYPE(NcObjectName, nc_object_name, NC, OBJECT_NAME, GObject)
/* METHODS */
NcObjectName *nc_object_name_new(gdouble prop1_val);
NcObjectName *nc_object_name_ref(NcObjectName *nc_object_name);
void nc_object_name_free(NcObjectName *nc_object_name);
void nc_object_name_clear(NcObjectName **nc_object_name);
G_END_DECLS
#endif /* _NC_OBJECT_NAME_H_ */Source for NcObjectName
/**
* NcObjectName:
*
* Object short description
*
* Long description
*
*/
#include "nc_object_name.h"
struct _NcObjectName
{
/*< private >*/
GObject parent_instance;
};
typedef struct _NcObjectNamePrivate
{
gdouble private_double;
} NcObjectNamePrivate;
enum
{
PROP_0,
PROP_PROP1,
PROP_SIZE,
};
/* This object is a child of GObject */
G_DEFINE_TYPE_WITH_PRIVATE (NcObjectName, nc_object_name, G_TYPE_OBJECT);
static void
nc_object_name_init (NcObjectName *obj)
{
NcObjectNamePrivate * const self = nc_object_name_get_instance_private (obj);
self->private_double = 0.0;
}
static void
_nc_object_name_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
NcObjectName *obj = NC_OBJECT_NAME (object);
NcObjectNamePrivate * const self = nc_object_name_get_instance_private (obj);
g_return_if_fail (NC_IS_OBJECT_NAME (object));
switch (prop_id)
{
case PROP_PROP1:
self->private_double = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
_nc_object_name_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NcObjectName *obj = NC_OBJECT_NAME (object);
NcObjectNamePrivate * const self = nc_object_name_get_instance_private (obj);
g_return_if_fail (NC_IS_OBJECT_NAME (object));
switch (prop_id)
{
case PROP_PROP1:
g_value_set_double (value, self->private_double);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
_nc_object_name_dispose (GObject *object)
{
/* Chain up : end */
G_OBJECT_CLASS (nc_object_name_parent_class)->dispose (object);
}
static void
_nc_object_name_finalize (GObject *object)
{
/* Chain up : end */
G_OBJECT_CLASS (nc_object_name_parent_class)->finalize (object);
}
static void
nc_object_name_class_init (NcObjectNameClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = &_nc_object_name_set_property;
object_class->get_property = &_nc_object_name_get_property;
object_class->dispose = &_nc_object_name_dispose;
object_class->finalize = &_nc_object_name_finalize;
g_object_class_install_property (object_class,
PROP_PROP1,
g_param_spec_double ("prop1",
NULL,
"This is prop is a double between (0.0, 1.0), default 0.5 ",
0.0, 1.0, 0.5,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB));
}
/* METHODS */
/**
* nc_object_name_new:
* @prop1: a value for prop1
*
* A simple constructor.
*
* Returns: (transfer full): a newly created #NcObjectName
*/
NcObjectName *
nc_object_name_new (gdouble prop1_val)
{
NcObjectName *nc_object_name = g_object_new (NC_TYPE_OBJECT_NAME,
"prop1", prop1_val,
NULL);
return nc_object_name;
}
/**
* nc_object_name_ref:
* @nc_object_name: a #NcObjectName
*
* Increase reference count by one.
*
* Returns: (transfer full): @nc_object_name.
*/
NcObjectName *
nc_object_name_ref (NcObjectName *nc_object_name)
{
return g_object_ref (nc_object_name);
}
/**
* nc_object_name_free:
* @nc_object_name: a #NcObjectName
*
* Decrease reference count by one.
*
*/
void
nc_object_name_free (NcObjectName *nc_object_name)
{
g_object_unref (nc_object_name);
}
/**
* nc_object_name_clear:
* @nc_object_name: a #NcObjectName
*
* Decrease reference count by one if *@nc_object_name != NULL
* and sets @nc_object_name to NULL.
*
*/
void
nc_object_name_clear (NcObjectName **nc_object_name)
{
g_clear_object (nc_object_name);
}