gjs

g_object_get_property: can't retrieve property '....' of type 'gchararray' as value of type 'GValue'


I try to understand the whole GObject stuff and tried a class with three properties, where two properties have getter and setters: 'example-property-a', 'example-property-b'
Each emit the notify signal different.
'example-property-a' emits, whenever the property changed its value.
'example-property-b' emits, whenever the property is set.

for 'example-property-c' i dont use a getter or setter.
i use the GObject instance methods.
instance.set_property ([ property name STR] , [value STR] );
instance.get_property ([ property name STR] , [value GValue] );

https://docs.gtk.org/gobject/method.Object.get_property.html says a GValue is needed as parameter.
But i get an error :g_object_get_property: can't retrieve property 'example-property-c' of type 'gchararray' as value of type 'GValue'

hm ... how to get a gchararray? - the complete class try

const GOBJECT = imports.gi.GObject;

//-- prefix: 'go_' ... instances of classes and classes themselves, which inherit from GOBJECT.Object have this prefix
const go_Example = GOBJECT.registerClass(
    {
    GTypeName: 'SubclassExample',
    Properties: {
        'example-property-a': GOBJECT.ParamSpec.double('example-property-a', '', '', GOBJECT.ParamFlags.READWRITE, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0),
        'example-property-b': GOBJECT.ParamSpec.boolean('example-property-b', '', '', GOBJECT.ParamFlags.READWRITE, true),
        'example-property-c': GOBJECT.ParamSpec.string('example-property-c', '', '', GOBJECT.ParamFlags.READWRITE, null) },
    Signals: {
        'example-signal': { flags: GOBJECT.SignalFlags.RUN_LAST, param_types: [GOBJECT.TYPE_STRING], accumulator: GOBJECT.AccumulatorType.TRUE_HANDLED, return_type: GOBJECT.TYPE_BOOLEAN } }
    },
    class go_Example extends GOBJECT.Object
        {
        _init (properties) //-- _init ... name of the constructor in GObject classes
            {
            //-- set standard defined above in properties
            this._example_property_a=0;
            this._example_property_b=true;
            this.example_property_c=null;
            super._init(properties);
            }

    //-- 'example_property_a' get, set link on '_example_property_a' -> notify, only if value has changed
    get example_property_a ()      { return this._example_property_a; }
    set example_property_a (value) { if (this._example_property_a === value) return; this._example_property_a = value; this.notify ("example-property-a"); }

    //-- 'example_property_b' get, set link on '_example_property_b'; notify, if value is set
    get example_property_b ()      { return this._example_property_b; }
    set example_property_b (value) { this._example_property_b = value; this.notify ("example-property-b"); }

    //-- no get, set of example_propertyC -> notify over GOBJECT.Object.set_property function
    });

let go_Obj=new go_Example ({example_property_a:12.5585, example_property_b:true, example_property_c: "hello world"});
let GValue_RV=new GOBJECT.Value; //-- return Value
GValue_RV.init(GOBJECT.TYPE_STRING)
go_Obj.connect ("notify::example-property-c", function (instance, ParamSpec) {log (instance+" - "+ParamSpec.get_name ());});
go_Obj.set_property ("example-property-c","hello");
go_Obj.get_property ("example-property-c",GValue_RV);
log (GValue_RV.get_string());

here i construct a GValue for returning the value of get_property

let GValue_RV=new GOBJECT.Value; //-- return Value
GValue_RV.init(GOBJECT.TYPE_STRING)

whats wrong?

other questions- if i construct a GObject.Object instance, can i install a ParamSpec property on a special object instance, because i only found install properties on a complete class?


Solution

  • Usually you won't want to use GObject.get_property() or GObject.set_property() in GJS. Instead you should just use the native accessors and allow GJS to do the heavy lifting for you:

    const myObject = new MyObject();
    
    // Getting a property
    let stringValue = myObject.example_property_c;
    
    // Setting a property
    myObject.example_property_c = 'string value';
    

    There is an introduction to GObject and a more thorough guide on subclassing on the gjs.guide website:

    if i construct a GObject.Object instance, can i install a ParamSpec property on a special object instance, because i only found install properties on a complete class?

    No, you can only install GObject properties on a class when it is defined, not on an instance. You can, however, add native JavaScript properties with Object.defineProperty().