Lexx129
Lexx129

Reputation: 43

Creating gtk signal for editing GtkWidget running in other thread

I have an app, which basically runs in terminal mode, but it can open it's GUI part in another thread (Simple window with a GtkTextView to print some messages out). I need to manually update the contents of this GtkTextView when some event happens in main thread. For that purpose I created a 'new-message-received' signal which should pass a pointer to char array msg with message to print

Creating new signal:

g_signal_new("new-message-received",
              G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST,
              0, NULL, NULL,
              g_cclosure_marshal_VOID__POINTER,
              G_TYPE_NONE, 1, G_TYPE_POINTER);

Connecting it with handler function:

g_signal_connect(G_OBJECT(demo_window), "new-message-received", 
                 G_CALLBACK(print_demo_message),(gpointer)msg);

And emitting signal:

if (flag){
memset(msg, 0, 256);
g_signal_emit_by_name(G_OBJECT(demo_window), 
                     "new-message-received", 
                     (gpointer) msg);
...
}

The problem is that signal handler gets some broken pointer (I try to print it to stdout -- it's always some random 4 symbols) instead of passed message. The handler is:

void print_demo_message(gpointer *param)
{
    const gchar* message = (const gchar*)param;
    g_print("Got message: %s\n", message);
    ...
}

The output is like:

Got message: p���

What I tried:

  1. Making msg a global variable to avoid re-initialization -- no result
  2. Using a generic marshaller in signal creating -- no result
  3. Passing a link to msg address instead of a pointer to it, no result too.

The question is -- what am I doing wrong?

Thanks in advance.

Upvotes: 1

Views: 214

Answers (1)

Lexx129
Lexx129

Reputation: 43

Had to solve this myself, there was no need in using signals at all.

Main thread for GTK is a thread, where gtk_main() is called from. Accessing any GTK object outside it's main thread is forbidden. So, to initiate a thread for GTK GUI I used g_thread_new() and g_idle_add(print_demo_message, msg) to "ask" GTK main thread to paste the msg to GtkTextView.

So, now it look like this:

APP MAIN THREAD:

if(%some_condition%){
     msg = malloc(256);
     sprintf(msg, "Some text");
     g_idle_add(print_demo_message, msg);
}

GUI THREAD:

boolean print_demo_message(gpointer data)
{
    gchar* message = data;
    g_print("Got message: %s\n", message);
 ...
}

Message transferred OK, works like charm :)

Upvotes: 2

Related Questions