static VALUE interface_s_properties(int argc, VALUE* argv, VALUE self) { guint n_properties; GParamSpec** props; VALUE inherited_too; VALUE ary = rb_ary_new(); guint i; gpointer ginterface; GType gtype = CLASS2GTYPE(self); if (rb_scan_args(argc, argv, "01", &inherited_too) == 0) inherited_too = Qtrue; if (!G_TYPE_IS_INTERFACE(gtype)) rb_raise(rb_eTypeError, "%s isn't interface module", rb_class2name(self)); /* XXX: g_type_default_interface_ref(G_TYPE_INTERFACE) causes SEGV. */ if (gtype == G_TYPE_INTERFACE) return ary; ginterface = g_type_default_interface_ref(gtype); props = g_object_interface_list_properties(ginterface, &n_properties); for (i = 0; i < n_properties; i++){ if (RVAL2CBOOL(inherited_too) || GTYPE2CLASS(props[i]->owner_type) == self) rb_ary_push(ary, rb_str_new2(props[i]->name)); } g_free(props); g_type_default_interface_unref(ginterface); return ary; }
static void extension_subclass_init (GObjectClass *klass, GType *exten_types) { guint i; guint property_id = 1; g_debug ("Initializing class '%s'", G_OBJECT_CLASS_NAME (klass)); klass->set_property = extension_subclass_set_property; klass->get_property = extension_subclass_get_property; for (i = 0; exten_types[i] != 0; ++i) { guint n_props, j; gpointer iface_vtable; GParamSpec **properties; iface_vtable = g_type_default_interface_peek (exten_types[i]); properties = g_object_interface_list_properties (iface_vtable, &n_props); for (j = 0; j < n_props; ++j, ++property_id) { const gchar *property_name; property_name = g_param_spec_get_name (properties[j]); g_object_class_override_property (klass, property_id, property_name); g_debug ("Overrided '%s:%s' for '%s' proxy", g_type_name (exten_types[i]), property_name, G_OBJECT_CLASS_NAME (klass)); } g_free (properties); } g_debug ("Initialized class '%s'", G_OBJECT_CLASS_NAME (klass)); }
// Until the glib bug https://bugzilla.gnome.org/show_bug.cgi?id=465631 // is fixed, get_properties() must be called for a GObject before it's // called for a GInterface. std::string get_properties(GType gtype) { std::string strResult; std::string strObjectName = g_type_name(gtype); // Get the list of properties: GParamSpec** ppParamSpec = nullptr; guint iCount = 0; if (G_TYPE_IS_OBJECT(gtype)) { GObjectClass* pGClass = G_OBJECT_CLASS(g_type_class_ref(gtype)); ppParamSpec = g_object_class_list_properties(pGClass, &iCount); g_type_class_unref(pGClass); if (!ppParamSpec) { strResult += ";; Warning: g_object_class_list_properties() returned NULL for " + std::string(g_type_name(gtype)) + "\n"; } } else if (G_TYPE_IS_INTERFACE(gtype)) { gpointer pGInterface = g_type_default_interface_ref(gtype); if (pGInterface) { ppParamSpec = g_object_interface_list_properties(pGInterface, &iCount); g_type_default_interface_unref(pGInterface); if (!ppParamSpec) { strResult += ";; Warning: g_object_interface_list_properties() returned NULL for " + std::string(g_type_name(gtype)) + "\n"; } } else strResult += ";; Warning: g_type_default_interface_ref() returned NULL for " + std::string(g_type_name(gtype)) + "\n"; } // This extra check avoids an occasional crash if (!ppParamSpec) iCount = 0; for (guint i = 0; i < iCount; i++) { GParamSpec* pParamSpec = ppParamSpec[i]; // Generate the property if the specified gtype actually owns the property. // (Generally all properties, including any base classes' properties are // retrieved by g_object_interface_list_properties() for a given gtype. // The base classes' properties should not be generated). if (pParamSpec && pParamSpec->owner_type == gtype) { strResult += get_property_with_node_name(pParamSpec, strObjectName, "define-property"); } } g_free(ppParamSpec); return strResult; }
void rbgobj_define_property_accessors(VALUE klass) { GType gtype; GParamSpec** pspecs = NULL; guint i; GString* source; guint n_properties = 0; gtype = CLASS2GTYPE(klass); if (G_TYPE_IS_INTERFACE(gtype)){ #if GLIB_CHECK_VERSION(2,4,0) gpointer iface = g_type_default_interface_ref(gtype); pspecs = g_object_interface_list_properties(iface, &n_properties); g_type_default_interface_unref(iface); #endif } else { GObjectClass* oclass = G_OBJECT_CLASS(g_type_class_ref(gtype)); pspecs = g_object_class_list_properties(oclass, &n_properties); g_type_class_unref(oclass); } if (n_properties == 0) return; source = g_string_new(NULL); for (i = 0; i < n_properties; i++){ GParamSpec* pspec = pspecs[i]; char* buf; char* prop_name; char* p; if (pspec->owner_type != gtype) continue; buf = g_strdup(pspec->name); for (p = buf; *p; p++) if (*p == '-') *p = '_'; if (!strncmp(buf, "is_", 3)) prop_name = buf + 3; else prop_name = buf; if (g_hash_table_lookup(prop_exclude_list, prop_name)){ g_free(buf); continue; } if (pspec->flags & G_PARAM_READABLE){ g_string_append_printf( source, "def %s%s; get_property('%s'); end\n", prop_name, (G_PARAM_SPEC_VALUE_TYPE(pspec) == G_TYPE_BOOLEAN) ? "?" : "", pspec->name); } if (IS_FLAG(pspec->flags, G_PARAM_WRITABLE) && !IS_FLAG(pspec->flags, G_PARAM_CONSTRUCT_ONLY)){ g_string_append_printf(source, "def set_%s(val); set_property('%s', val); end\n", prop_name, pspec->name); #ifdef HAVE_NODE_ATTRASGN g_string_append_printf(source, "alias %s= set_%s\n", prop_name, prop_name); #else g_string_append_printf(source, "def %s=(val); set_property('%s', val); val; end\n", prop_name, pspec->name); #endif } g_free(buf); } if (source->len > 0) rb_funcall(klass, id_module_eval, 1, rb_str_new2(source->str)); g_string_free(source, TRUE); }