Search code examples
cglibgobject

gobject overwrite property in derived class


I'm trying to read files in EDF format. The EDF format is quite old (1990s). It exists of an header in ASCII format and a large number of sample from different transducers; think of EEG, ECG or another type of electrode with samples that is converted to a digital value. Each transducer is called a signal. EDF samples come in little endian 2s complement 16 bit samples. The header of the file will tell which signals are present and how they appear.

However as time goes by a dialect of EDF has been designed, called BDF which is largely equal to EDF, but it can contain samples similar to EDF but with 24 bits of precision.

Now I'm trying to make a GObject style EdfFile, EdfHeader and EdfSignal class. The BDF equivalants are EdfBdfFile, EdfBdfHeader and EdfBdfSigal. All BDF file derive from there Edf equivalents.

The EdfSignal has two properties that I would like to override in EdfBdfSignal, namely "digital-min" and "digital-max".

I'm trying to do this as follows:

edf-signal.c:

static void
edf_signal_class_init(EdfSignalClass* klass)
{
    GObjectClass* object_class = G_OBJECT_CLASS(klass);

    object_class->set_property = edf_signal_set_property;
    object_class->get_property = edf_signal_get_property;
    object_class->dispose = edf_signal_dispose;
    object_class->finalize = edf_signal_finalize;

    klass->append_new_record = append_new_record;

    // A number of other properties here

    edf_signal_properties [PROP_DIGITAL_MIN] = g_param_spec_int(
            "digital-min",
            "digital-minimum",
            "The digital minimum of an signal",
            G_MININT16,
            G_MAXINT16,
            0,
            G_PARAM_READWRITE
            );

    edf_signal_properties [PROP_DIGITAL_MAX] = g_param_spec_int(
            "digital-max",
            "digital-maximum",
            "The digital maximum of an signal",
            G_MININT16,
            G_MAXINT16,
            0,
            G_PARAM_READWRITE
            );
    // Some more properties here.

    g_object_class_install_properties(
            object_class, N_PROPERTIES, edf_signal_properties
            );
}

And I try to override the properties in de deriving class edf-bdf-signal.c:

static void
edf_bdf_signal_class_init(EdfBdfSignalClass* klass)
{
    GObjectClass* object_class = G_OBJECT_CLASS(klass);
    object_class->set_property = set_property;
    object_class->get_property = get_property;
    EdfSignalClass* signal_class = EDF_SIGNAL_CLASS(klass);

    signal_class->append_new_record = append_new_record;

    // I would like to name these properties "digital-max" and
    // "digital-min" as well, but the gobject type system
    // doesn't like that.

    obj_properties[PROP_DIGITAL_MAX] = g_param_spec_int(
        "bdf-digital-max",
        "Digital-Max",
        "The digital maximum of a BdfFile.",
        -8388608,
        8388607,
        0,
        G_PARAM_READWRITE | G_PARAM_CONSTRUCT
        );

    obj_properties[PROP_DIGITAL_MIN] = g_param_spec_int(
        "bdf-digital-min",
        "Digital-Min",
        "The digital minimum of a BdfFile.",
        -8388608,
        8388607,
        0,
        G_PARAM_READWRITE | G_PARAM_CONSTRUCT
    );

    g_object_class_override_property(object_class, PROP_DIGITAL_MAX, "digital-max");
    g_object_class_override_property(object_class, PROP_DIGITAL_MIN, "digital-min");

    g_object_class_install_properties(object_class, N_PROPERTIES, obj_properties);

}

If I'm now reading a BDF file I stumble across errors such as:

ok 1 /BdfFile/create Bail out! GLib-GObject-FATAL-WARNING: value "-8388608" of type 'gint' is invalid or out of range for property 'digital-min' of type 'gint'

(/home/maarten/github/eeg-fft/debug/test/unittest:7085): GLib-GObject-WARNING **: 11:22:30.745: value "-8388608" of type 'gint' is invalid or out of range for property 'digital-min' of type 'gint'

This tells me that I have not been successful in overriding the property. Because -8388608 should be valid in a EdfBdfSignal, but invalid in a EdfSignal. I hope to know whether it is possible to do so.


Solution

  • You don’t need the g_param_spec_int() calls in edf_bdf_signal_class_init() to override the properties — you only need the g_object_class_override_property() calls.

    Overriding the properties doesn’t allow you to change the maximum/minimum used for validating the property values, which it looks like you’re attempting to do. If you were to do so, it would break the type system: if you had a variable which was an instance of EdfBdfSignal, but which was being processed by some generic code as an EdfSignal, that generic code should expect to receive a 16-bit value if it gets the value of digital-max (for example). It could end up receiving a larger-than-16-bit value though.

    Without knowing the structure of the rest of your code I can’t confidently suggest a solution for this. I would consider either:

    • Relaxing the minimum/maximum values for digital-max and digital-min in EdfSignal so that they can accommodate the values used by EdfBdfSignal. You could potentially add an additional read-only property which gives the bit width of digital-max/digital-min: it would have a value of 16 for EdfSignal and a value of 24 for EdfBdfSignal.
    • Changing EdfBdfSignal to not derive from EdfSignal, and instead be a parallel implementation. Both classes would implement an interface for common functionality, but that interface would not define the digital-min/digital-max properties. The implementations and ranges of those properties could then be independent in EdfSignal and EdfBdfSignal.