luc.chante
luc.chante

Reputation: 440

segmentation fault with object instance and signal handler in vala

I'm writting a little http client to test api calls. This is the occasion for learning vala and using gtk3.

I made a class to deal with gtk interface and http request.

using GLib;
using Gtk;

public class RequestHandler : Object
{
    public string uri { get; private set; default = ""; }

    // Constructor
    public RequestHandler ()
    {
    }

    [CCode (instance_pos = -1)]
    public void on_url_changed (Entry entry, Button button)
    {
        stderr.printf ("this#%p\n", this);
        if (entry.get_text_length () == 0)
        {
            button.set_sensitive (false);
            this.uri = "";
        }
        else
        {
            button.set_sensitive (true);
            this.uri = entry.get_text();
        }
    }

    [CCode (instance_pos = -1)]
    public void on_send_clicked (Button button)
    {
        assert (this.uri != null );
        stderr.printf ("Send request to : %s\n", this.uri);
    }
}

The line

stderr.printf ("this#%p\n", this);
// => fprintf (_tmp0_, "this#%p\n", self); in the C file

display every time "this#0x1" and the program failed with segmentation fault at the line

this.uri = entry.get_text();
// _g_free0 (self->priv->_uri); in the C file

The UI is build with

var builder = new Builder ();
builder.add_from_file (UI_FILE);
var signals_handler = new RequestHandler ();
builder.connect_signals (signals_handler);

I'm really a newbie in vala and I don't see my mistake.

[edit]

...
<object class="GtkEntry" id="entry2">
    <property name="visible">True</property>
    <property name="can_focus">True</property>
    <property name="receives_default">True</property>
    <property name="hexpand">True</property>
    <property name="invisible_char">●</property>
    <property name="input_purpose">url</property>
    <signal name="changed" handler="request_handler_on_url_changed" object="button1" swapped="no"/>
</object>
...

The ui is fully generated with glade.

Upvotes: 0

Views: 420

Answers (1)

nemequ
nemequ

Reputation: 17522

You have an extra argument on the on_url_changed method. The Gtk.Editable.changed signal should have a single argument: the Gtk.Editable which changed. Since there is no type safety with autoconnected signals, public void on_changed (Gtk.Entry entry); should work.

What is happening with the code you posted above is that something like this is being generated:

void request_handler_on_changed (GtkEntry* entry, GtkButton* button, RequestHandler* self) {
  fprintf (stderr, "this#%p\n", self);
}

And gtk+ is calling it like

request_handler_on_changed (editable, request_handler);

So, when your Vala code gets the information, it has the RequestHandler in the button argument, and self (which is how the "this" variable is generated) is garbage.

You have to be very careful when autoconnecting signals because you're basically circumventing Vala and hooking directly in to the generated C. Vala has no way to provide type safety.

Upvotes: 1

Related Questions