[Vala] inherited method attributes: instancepos inconsistencies



(In preparation for Nicolas idea on GTK bindings of events, avoiding the
need for exported symbols)

The [CCode] attributes aren't being inherited with override methods AND
aren't being checked, see this sample code:

public class PhoneDialer : Gtk.Object {
  construct {
    GLib.Signal.connect(this.widgets.button_undo, "clicked",
(GLib.Callback) on_button_undo_clicked, this);
  }
 
  [CCode (instance_pos = -1)]
  public virtual void on_button_undo_clicked (Gtk.Widget widget) { }
}

public class GladePhoneUI : PhoneDialer {
    [CCode (instance_pos = -1)]
    public override void on_button_undo_clicked (Gtk.Widget widget) {
        widgets.dialer_entry.backspace();
    }
}

If I remove the CCode in the subclass, then the virtual method is
invoked wrongly, with scrambled arguments, as we see by looking at the C
code below.

At a first look it seems as though the override method should inherit at
least some of the CCode attributes of the method they override.

A closer look shows something else, because two types of methods are
generated for virtual and overridden methos:

In the generated C, virtual methods have an entry method; like this,
which dispatches to the actual method.

void phone_dialer_on_button_undo_clicked (GtkWidget* widget,
PhoneDialer* self) {
    PHONE_DIALER_GET_CLASS (self)->on_button_undo_clicked (widget, self);
}

and then actual methods like this:
static void phone_dialer_real_on_button_undo_clicked (GtkWidget* widget,
PhoneDialer* self) {
    g_return_if_fail (IS_PHONE_DIALER (self));
    g_return_if_fail (GTK_IS_WIDGET (widget));
}
and this, in the subclass, without a matching instance_pos
static void glade_phone_ui_real_on_button_undo_clicked (PhoneDialer*
base, GtkWidget* widget) {
    GladePhoneUI * self;
    self = GLADE_PHONE_UI (base);
    g_return_if_fail (GTK_IS_WIDGET (widget));
    g_signal_emit_by_name (G_OBJECT (PHONE_DIALER
(self)->widgets->dialer_entry), "backspace");
}

We see that the last function (above) has the arguments the wrong way
around because I had removed the instance_pos.

But in fact it is only the entry method that needs to take into account
instance_pos when ordering it's declared arguments.
The inner "real" methods can be "normal" without any strange calling
conventions, and the entry dispatching method could "know" this.

And so I'm really suggesting that for virtual methods, instance_pos only
apply to the wrapper and not to the real functions at all.
It would then be illegal to specify instance_pos on override methods,
only on virtual methods.

If this idea isn't taken up, then consistency should at least be
enforced across all overriddings of the method.

I note that with vala 3.3, an abstract virtual method fails, because the
class init does tries to initialize the "real" method but of course
there isn't one.
I suppose there could be a dummy one that raised an exception or set it
to NULL instead if it is abstract.

static void phone_dialer_class_init (PhoneDialerClass * klass) {
    phone_dialer_parent_class = g_type_class_peek_parent (klass);
    g_type_class_add_private (klass, sizeof (PhoneDialerPrivate));
    G_OBJECT_CLASS (klass)->constructor = phone_dialer_constructor;
    G_OBJECT_CLASS (klass)->dispose = phone_dialer_dispose;
    PHONE_DIALER_CLASS (klass)->on_button_undo_clicked =
phone_dialer_real_on_button_undo_clicked;
}


Sam



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]