First draft of interface property patch
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org, timj gtk org
- Subject: First draft of interface property patch
- Date: 17 Mar 2003 16:16:26 -0500
Hi Tim,
The attached is a first draft of an implementation of interface
properties along the lines you suggested.
(I used OVERRIDE as a paramspec flag name rather than TRANSLUCENT,
because I really don't like TRANSLUCENT. OVERRIDE isn't all that
wonderful, but it fits in well with
g_object_property_find_overridden())
The interface additions are:
===
G_PARAM_OVERRIDE = 1 << 6
void g_object_interface_install_property (GType iface_type,
GParamSpec *pspec);
GParamSpec* g_object_interface_find_property (GType iface_type,
const gchar *property_name);
GParamSpec**g_object_interface_list_properties (GType iface_type,
guint *n_properties_p);
GParamSpec* g_object_property_find_overridden (GParamSpec *pspec);
===
Comments:
* Doc comments are inline until the interfaces are finalized to
keep things simple. I'll move them later.
* Currently, there is no way of removing properties from interfaces
once added because:
a) We don't really have a class_init/class_finalize steps
for interfaces.
b) There is no way of hooking into class_finalize in any case.
If we think this capability is important, then one simple
possibility is to add a:
g_object_interface_remove_properties ()
That the user calls itself.
* interface_install_property() takes a GType rather than a class
pointer (like object_class_install_property()) because there is no
class for an interface, only vtables for implementations of that
interface.
* It's not clear to me when the checks for an object class
implementing all necessary properties should happen. The
patch currently does it in g_object_newv(), but:
a) that's pretty clearly too expensive (with some thread
locking trouble, you could manage to cache the info)
b) you can add interfaces after an object already exists.
The right point seems to be right after interface_init is
called for the class/interface pair, but there is no
way for gobject.c to hook into that.
* What are the constraints on parameter spec validation here?
It's a little interesting:
G_PARAM_READABLE:
The set of valid values for the interface property must
be a superset of the set of valid values for the implementation
property.
G_PARAM_WRITABLE:
The set of valid values for the interface property must
be a subset of the set of valid values for the implementation
property.
So, for the common case of READWRITE properties, these two
sets of valid values have to be identical. Changing the value
type of a GParamSpecObject property or the range of a
GParamSpecInt isn't a valid operation.
This doesn't have much affect on my patch, since this isn't
particularly enforceable, but I do check that the value types
are the same. (For conceptual simplicity, always, instead
of checking the appropriate derivation based on READABLE/WRITABLE)
* I expect some objects to the inclusion of gobject.h in gparam.h
to make g_param_spec_get_nick/blurb to magically look up
the overridden property.
I don't see a good alternative that maintains the same
degree of simplicity.
* I'm really not very happy with the need to copy ranges and
default values ... it's a pain and it's bugs waiting to happen.
Noting the above comments about changing the ranges, it
would be possible to add:
g_param_spec_new_override (gchar *name,
GType value_type,
GParamFlags flags);
g_param_spec_override_set_default (GParamSpecOverride *pspec);
That looked up the overriden paramspec and chained
value_validate() and (when default isn't set) value_set_default()
to that paramspec, without changing anything else.
The only possible problem with this is efficiency... looking
up the overriden paramspec is moderately expensive.
Regards,
Owen
Index: gobject.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/gobject.c,v
retrieving revision 1.57
diff -u -p -r1.57 gobject.c
--- gobject.c 7 Feb 2003 22:04:24 -0000 1.57
+++ gobject.c 17 Mar 2003 20:06:55 -0000
@@ -258,6 +258,25 @@ g_object_do_class_init (GObjectClass *cl
1, G_TYPE_PARAM);
}
+static void
+install_property_internal (GType g_type,
+ guint property_id,
+ GParamSpec *pspec)
+{
+ if (g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type, FALSE))
+ {
+ g_warning (G_STRLOC ": type `%s' already has a property named `%s'",
+ g_type_name (g_type),
+ pspec->name);
+ return;
+ }
+
+ g_param_spec_ref (pspec);
+ g_param_spec_sink (pspec);
+ PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
+ g_param_spec_pool_insert (pspec_pool, pspec, g_type);
+}
+
void
g_object_class_install_property (GObjectClass *class,
guint property_id,
@@ -276,18 +295,8 @@ g_object_class_install_property (GObject
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
- if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE))
- {
- g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
- G_OBJECT_CLASS_NAME (class),
- pspec->name);
- return;
- }
+ install_property_internal (G_OBJECT_CLASS_TYPE (class), property_id, pspec);
- g_param_spec_ref (pspec);
- g_param_spec_sink (pspec);
- PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
- g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
@@ -299,6 +308,33 @@ g_object_class_install_property (GObject
class->construct_properties = g_slist_remove (class->construct_properties, pspec);
}
+/**
+ * g_object_interface_install_property:
+ * @iface_type: an interface type
+ * @pspec: the #GParamSpec for the new property
+ *
+ * Add a property to an interface; this will only be useful
+ * if the interface is subsequently added to a GObject-derived
+ * type. Adding a property to an interface has two primary
+ * purposes. First, all object types with that interface will
+ * be required by GObject to implement a property with the
+ * same name and type. Second, the %G_PARAM_OVERRIDE flag can be
+ * used on the implementation properties to indicate that
+ * the nick and blurb should be looked up from the interface
+ * property when missing from the instance property.
+ * (See g_object_property_find_overridden ())
+ **/
+void
+g_object_interface_install_property (GType iface_type,
+ GParamSpec *pspec)
+{
+ g_return_if_fail (G_TYPE_IS_INTERFACE (iface_type));
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
+
+ install_property_internal (iface_type, 0, pspec);
+}
+
GParamSpec*
g_object_class_find_property (GObjectClass *class,
const gchar *property_name)
@@ -312,6 +348,104 @@ g_object_class_find_property (GObjectCla
TRUE);
}
+/**
+ * g_object_interface_find_property:
+ * @iface_type: an interface type
+ * @property_name: name of a property to lookup.
+ *
+ * Find the #GParamSpec with the given name for an
+ * interface.
+ *
+ * Return value: the #GParamSpec for the property of the
+ * interface with the name @property_name, or %NULL
+ * if no such property exists.
+ **/
+GParamSpec*
+g_object_interface_find_property (GType iface_type,
+ const gchar *property_name)
+{
+ g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_type), NULL);
+ g_return_val_if_fail (property_name != NULL, NULL);
+
+ return g_param_spec_pool_lookup (pspec_pool,
+ property_name,
+ iface_type,
+ FALSE);
+}
+
+/**
+ * g_object_property_find_overridden:
+ * @pspec: a #GParamSpec
+ *
+ * Given a property, finds the property that it overrides.
+ * Only properties with %G_PARAM_OVERRIDE flag set are
+ * ever considered to override another property. To
+ * find the property that such a property overrides,
+ * first the parent types of the property's owner
+ * type are checked, then the interfaces that the
+ * owner type implements.
+ *
+ * Return value: a #GParamSpec, or %NULL if this paramspec
+ * is not overriding another paramspec.
+ **/
+GParamSpec*
+g_object_property_find_overridden (GParamSpec *pspec)
+{
+ GParamSpec *result;
+ GType owner_type;
+ GType parent_type;
+ GType *ifaces;
+ guint n_ifaces;
+
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
+
+ if (!(pspec->flags & G_PARAM_OVERRIDE))
+ return NULL;
+
+ owner_type = pspec->owner_type;
+ if (!owner_type || G_TYPE_IS_INTERFACE (owner_type))
+ return NULL;
+
+ if (!G_TYPE_IS_OBJECT (owner_type))
+ {
+ g_warning ("Owner type in g_object_property_find_overridden() "
+ "does not derive from GObject\n");
+ return NULL;
+ }
+
+ result = NULL;
+
+ /* First check parent types
+ */
+ parent_type = g_type_parent (owner_type);
+ if (parent_type != G_TYPE_NONE)
+ result = g_param_spec_pool_lookup (pspec_pool,
+ pspec->name,
+ parent_type,
+ TRUE);
+
+ if (result)
+ return result;
+
+ /* Now check interfaces
+ */
+ ifaces = g_type_interfaces (owner_type, &n_ifaces);
+ while (n_ifaces-- && !result)
+ {
+ result = g_param_spec_pool_lookup (pspec_pool,
+ pspec->name,
+ ifaces[n_ifaces],
+ FALSE);
+
+ if (result)
+ break;
+ }
+
+ g_free (ifaces);
+
+ return result;
+}
+
GParamSpec** /* free result */
g_object_class_list_properties (GObjectClass *class,
guint *n_properties_p)
@@ -330,6 +464,38 @@ g_object_class_list_properties (GObjectC
return pspecs;
}
+/**
+ * g_object_interface_list_properties:
+ * @iface_type: an interface type
+ * @n_properties_p: location to store number of properties
+ * returned.
+ *
+ * Lists the properties of a given interface.
+ *
+ * Return value: a pointer to an array of pointers to
+ * #GParamSpec structures. The structures
+ * are owned by GLib, but the array should
+ * be freed with g_free() when you are
+ * done with it.
+ **/
+GParamSpec** /* free result */
+g_object_interface_list_properties (GType iface_type,
+ guint *n_properties_p)
+{
+ GParamSpec **pspecs;
+ guint n;
+
+ g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_type), NULL);
+
+ pspecs = g_param_spec_pool_list (pspec_pool,
+ iface_type,
+ &n);
+ if (n_properties_p)
+ *n_properties_p = n;
+
+ return pspecs;
+}
+
static void
g_object_init (GObject *object)
{
@@ -591,6 +757,99 @@ g_object_new (GType object_type,
return object;
}
+static gboolean
+g_object_class_check_iface_properties (GObjectClass *class)
+{
+ GType *ifaces;
+ guint n_ifaces;
+ gboolean result;
+
+ ifaces = g_type_interfaces (G_OBJECT_CLASS_TYPE (class), &n_ifaces);
+
+ /* The behavior will be undefined if multiple interfaces
+ * define the same property, and the OVERRIDE flag is used; we
+ * don't try to check for that here
+ */
+
+ result = TRUE;
+ while (n_ifaces--)
+ {
+ GParamSpec **pspecs;
+ guint n;
+
+ pspecs = g_param_spec_pool_list (pspec_pool, ifaces[n_ifaces], &n);
+
+ while (n--)
+ {
+ GParamSpec *class_pspec = g_object_class_find_property (class, pspecs[n]->name);
+
+ if (!class_pspec)
+ {
+ g_critical ("Object class %s doesn't implement property "
+ "'%s' from interface '%s'",
+ g_type_name (G_OBJECT_CLASS_TYPE (class)),
+ pspecs[n]->name,
+ g_type_name (ifaces[n_ifaces]));
+ result = FALSE;
+ }
+
+ /* The implementation paramspec must have a less
+ * restrictive type than the interface parameter
+ * spec for set() and a more restrictive type for
+ * get(), so we just require equality. (Though we
+ * could theoretically check the READABLE and
+ * WRITABLE flags) Should we also check
+ * G_PARAM_SPEC_TYPE?
+ */
+ if (class_pspec &&
+ !g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (pspecs[n]),
+ G_PARAM_SPEC_VALUE_TYPE (class_pspec)))
+ {
+ g_critical ("Property '%s' on class '%s' has type '%s' "
+ "which is different from the type '%s', "
+ "of the property on interface '%s'\n",
+ pspecs[n]->name,
+ g_type_name (G_OBJECT_CLASS_TYPE (class)),
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (class_pspec)),
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspecs[n])),
+ g_type_name (ifaces[n_ifaces]));
+
+ result = FALSE;
+ }
+
+#define SUBSET(a,b,mask) (((a) & ~(b) & (mask)) == 0)
+
+ /* CONSTRUCT and CONSTRUCT_ONLY add restrictions.
+ * READABLE and WRITABLE remove restrictions
+ */
+ if (class_pspec &&
+ (!SUBSET (class_pspec->flags,
+ pspecs[n]->flags,
+ G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY) ||
+ !SUBSET (pspecs[n]->flags,
+ class_pspec->flags,
+ G_PARAM_READABLE | G_PARAM_WRITABLE)))
+ {
+ g_critical ("Flags for property '%s' on class '%s' "
+ "are not compatible with the property on"
+ "interface '%s'\n",
+ pspecs[n]->name,
+ g_type_name (G_OBJECT_CLASS_TYPE (class)),
+ g_type_name (ifaces[n_ifaces]));
+
+ result = FALSE;
+ }
+#undef SUBSET
+ }
+
+ g_free (pspecs);
+ }
+
+ g_free (ifaces);
+
+ return result;
+}
+
gpointer
g_object_newv (GType object_type,
guint n_parameters,
@@ -609,6 +868,10 @@ g_object_newv (GType object_type,
g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
class = g_type_class_ref (object_type);
+
+ if (!g_object_class_check_iface_properties (class))
+ return NULL;
+
for (slist = class->construct_properties; slist; slist = slist->next)
{
clist = g_list_prepend (clist, slist->data);
Index: gobject.h
===================================================================
RCS file: /cvs/gnome/glib/gobject/gobject.h,v
retrieving revision 1.26
diff -u -p -r1.26 gobject.h
--- gobject.h 21 Mar 2002 00:34:04 -0000 1.26
+++ gobject.h 17 Mar 2003 20:06:55 -0000
@@ -116,6 +116,15 @@ GParamSpec* g_object_class_find_property
const gchar *property_name);
GParamSpec**g_object_class_list_properties (GObjectClass *oclass,
guint *n_properties);
+
+void g_object_interface_install_property (GType iface_type,
+ GParamSpec *pspec);
+GParamSpec* g_object_interface_find_property (GType iface_type,
+ const gchar *property_name);
+GParamSpec**g_object_interface_list_properties (GType iface_type,
+ guint *n_properties_p);
+GParamSpec* g_object_property_find_overridden (GParamSpec *pspec);
+
gpointer g_object_new (GType object_type,
const gchar *first_property_name,
...);
Index: gparam.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/gparam.c,v
retrieving revision 1.27
diff -u -p -r1.27 gparam.c
--- gparam.c 7 Feb 2003 22:04:24 -0000 1.27
+++ gparam.c 17 Mar 2003 20:06:55 -0000
@@ -21,6 +21,7 @@
* MT safe
*/
+#include "gobject.h"
#include "gparam.h"
@@ -246,7 +247,20 @@ g_param_spec_get_nick (GParamSpec *pspec
{
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
- return pspec->_nick ? pspec->_nick : pspec->name;
+ if (pspec->_nick)
+ return pspec->_nick;
+ else if (pspec->flags & G_PARAM_OVERRIDE &&
+ pspec->owner_type != G_TYPE_NONE &&
+ G_TYPE_IS_OBJECT (pspec->owner_type))
+ {
+ GParamSpec *overridden;
+
+ overridden = g_object_property_find_overridden (pspec);
+ if (overridden && overridden->_nick)
+ return overridden->_nick;
+ }
+
+ return pspec->name;
}
G_CONST_RETURN gchar*
@@ -254,7 +268,20 @@ g_param_spec_get_blurb (GParamSpec *pspe
{
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
- return pspec->_blurb;
+ if (pspec->_blurb)
+ return pspec->_blurb;
+ else if (pspec->flags & G_PARAM_OVERRIDE &&
+ pspec->owner_type != G_TYPE_NONE &&
+ G_TYPE_IS_OBJECT (pspec->owner_type))
+ {
+ GParamSpec *overridden;
+
+ overridden = g_object_property_find_overridden (pspec);
+ if (overridden && overridden->_blurb)
+ return overridden->_blurb;
+ }
+
+ return NULL;
}
static void
Index: gparam.h
===================================================================
RCS file: /cvs/gnome/glib/gobject/gparam.h,v
retrieving revision 1.22
diff -u -p -r1.22 gparam.h
--- gparam.h 3 Mar 2002 03:14:43 -0000 1.22
+++ gparam.h 17 Mar 2003 20:06:55 -0000
@@ -53,7 +53,8 @@ typedef enum
G_PARAM_CONSTRUCT = 1 << 2,
G_PARAM_CONSTRUCT_ONLY = 1 << 3,
G_PARAM_LAX_VALIDATION = 1 << 4,
- G_PARAM_PRIVATE = 1 << 5
+ G_PARAM_PRIVATE = 1 << 5,
+ G_PARAM_OVERRIDE = 1 << 6
} GParamFlags;
#define G_PARAM_READWRITE (G_PARAM_READABLE | G_PARAM_WRITABLE)
#define G_PARAM_MASK (0x000000ff)
@@ -73,7 +74,7 @@ struct _GParamSpec
gchar *name;
GParamFlags flags;
GType value_type;
- GType owner_type; /* class using this property */
+ GType owner_type; /* class or interface using this property */
/*< private >*/
gchar *_nick;
Index: testgobject.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/testgobject.c,v
retrieving revision 1.7
diff -u -p -r1.7 testgobject.c
--- testgobject.c 10 Mar 2003 16:41:28 -0000 1.7
+++ testgobject.c 17 Mar 2003 20:06:55 -0000
@@ -40,6 +40,16 @@ static void iface_base_init (TestIfaceC
static void iface_base_finalize (TestIfaceClass *iface);
static void print_foo (TestIface *tiobj,
const gchar *string);
+
+enum {
+ PROP_0,
+ PROP_TESTINT1
+};
+
+
+#define PROP_TESTINT1_NICK "Test Int 1"
+#define PROP_TESTINT1_BLURB "First test integer"
+
GType
test_iface_get_type (void)
{
@@ -64,11 +74,35 @@ static guint iface_base_init_count = 0;
static void
iface_base_init (TestIfaceClass *iface)
{
+ static gboolean initialized = FALSE;
+
iface_base_init_count++;
if (iface_base_init_count == 1)
{
/* add signals here */
}
+
+ if (!initialized)
+ {
+ /* We can't remove properties, so we have to make sure
+ * to add them only _once_.
+ */
+ initialized = TRUE;
+
+ /* In the implementation, we'll add the READABLE flag
+ * remove the CONSTRUCT_ONLY flag ... both changes makes
+ * things less restrictive, so are OK.
+ */
+ g_object_interface_install_property (G_TYPE_FROM_INTERFACE (iface),
+ g_param_spec_int ("testint1",
+ PROP_TESTINT1_NICK,
+ PROP_TESTINT1_BLURB,
+ G_MININT, /* min */
+ G_MAXINT, /* max */
+ 0, /* default */
+ (G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY)));
+ }
}
static void
iface_base_finalize (TestIfaceClass *iface)
@@ -149,6 +183,14 @@ struct _TestObjectPrivate
};
static void test_object_class_init (TestObjectClass *class);
static void test_object_init (TestObject *tobject);
+static void test_object_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void test_object_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
static gboolean test_signal_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
@@ -186,8 +228,11 @@ test_object_get_type (void)
static void
test_object_class_init (TestObjectClass *class)
{
- /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ gobject_class->set_property = test_object_set_property;
+ gobject_class->get_property = test_object_get_property;
+
class->test_signal = test_object_test_signal;
g_signal_new ("test-signal",
@@ -198,6 +243,17 @@ test_object_class_init (TestObjectClass
g_cclosure_marshal_STRING__OBJECT_POINTER,
G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER);
+ g_object_class_install_property (gobject_class,
+ PROP_TESTINT1,
+ g_param_spec_int ("testint1",
+ NULL,
+ NULL,
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_OVERRIDE));
+
g_type_class_add_private (class, sizeof (TestObjectPrivate));
}
static void
@@ -210,6 +266,46 @@ test_object_init (TestObject *tobject)
g_assert (priv);
g_assert ((gchar *)priv >= (gchar *)tobject + sizeof (TestObject));
}
+static void
+test_object_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TestObjectPrivate *priv;
+
+ priv = TEST_OBJECT_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_TESTINT1:
+ priv->dummy1 = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+static void
+test_object_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TestObjectPrivate *priv;
+
+ priv = TEST_OBJECT_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_TESTINT1:
+ g_value_set_int (value, priv->dummy1);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
static gboolean
test_signal_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
@@ -360,6 +456,9 @@ main (int argc,
TestObject *sigarg;
DerivedObject *dobject;
gchar *string = NULL;
+ TestObjectClass *test_class;
+ GParamSpec *pspec;
+ gint int_result;
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
@@ -376,10 +475,23 @@ main (int argc,
g_assert (g_type_from_name ("FooShadow2") == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 1));
/* to test past class initialization interface setups, create the class here */
- g_type_class_ref (TEST_TYPE_OBJECT);
+ test_class = g_type_class_ref (TEST_TYPE_OBJECT);
+ /* Test redirection of nick/blurb from overriding properties
+ */
+ pspec = g_object_class_find_property (G_OBJECT_CLASS (test_class),
+ "testint1");
+ g_assert (strcmp (g_param_spec_get_nick (pspec), PROP_TESTINT1_NICK) == 0);
+ g_assert (strcmp (g_param_spec_get_blurb (pspec), PROP_TESTINT1_BLURB) == 0);
+
dobject = g_object_new (DERIVED_TYPE_OBJECT, NULL);
sigarg = g_object_new (TEST_TYPE_OBJECT, NULL);
+
+ /* Test setting and getting properties
+ */
+ g_object_set (dobject, "testint1", 42, NULL);
+ g_object_get (dobject, "testint1", &int_result, NULL);
+ g_assert (int_result == 42);
g_print ("MAIN: emit test-signal:\n");
g_signal_emit_by_name (dobject, "test-signal", sigarg, NULL, &string);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]