Passing user data to Callback function using glade - c

I am using glade to make my .ui files and then using GtkBuilder I am loading that whole .ui file in my C program, so all the widgets and stuff are created from the builder files itself.
Earlier I had been creating widgets only from the code itself, hence allowing me to pass any type of data to the Callback since the second argument is a gpointer variable and I could anytime create a pointer to a custom made structure and pass any type of data to the callbacks.
But now to connect to the signals I am just using this simple function :
gtk_builder_connect_signals(builder, NULL);
where builder is a pointer to GtkBuilder.
This connects all the signals mentioned in glade file with those of function defined in the .c files without having any provision of passing user_data other than that of Widgets (which themselves can only be defined in glade.)
Can anybody tell me a solution so that I can pass any type of data to my callbacks. I don't want to leave glade since it saves lot of my time, hence I would not like to switch over to traditional way of creating widgets by code only.
An example using both g_connect_signal() and gtk_builder_connect_signals() would be helpful. In this case which one to call first to override signal connection.

You can call gtk_builder_get_object to retrieve any widget created by Glade given the widget's name. Then you can connect the widget to the signals with the usual g_connect_signal API. The drawback is that you can no longer simply "mention" signals in the glade definition.
The other way is to also use gtk_builder_get_object to get the object, but to call g_object_set_qdata to associate the necessary user data with a GQuark key known to you. Your callback can then pick up the user data from the widget using g_object_get_qdata with the same key. This has the advantage that you would still be using gtk_builder_connect_signals.

That NULL pointer you are passing in is for the user data pointer.
gtk_builder_connect_signals(builder, NULL);
^
here----------------------------------|
If you always have the same user data object then your problem is solved. If not you
will need some kind of data structure for the different user data pointers so that
each callback can find the correct one.

Related

Transferring data to/from a callback from/to a worker thread

My current application is a toy web service written in C designed to replicate the behaviour of http://sprunge.us/ (takes data in via http POST, stores it to disk, returns the client a url to the data - also serves data that has been previously stored upon request).
The application is structured such that a thread pool is instantiated with worker threads (just a function pointer that takes a void* parameter) and a socket is opened to listen to incoming connections. The main loop of the program comprises a sock = accept(...) call and then a pool_add_task(worker_function_parse_http, sock) to enable requests to be handled quickly.
The parse_http worker parses the incoming request and either adds another task to the work queue for storing the data (POST) or serving previously stored data (GET).
My problem with this approach stems from the use of the http-parser library which uses a callback design to return parsed data (all http parsers that I looked at used this style). The problem I encounter is as such:
My parse_http worker:
Buffers data from the accepted socket (the function's only parameter, at this stage)
Sets up a http-parser object as per its API, complete with setting callback functions for it to call when it finishes parsing the URL or BODY or whatever. (These functions are of a fixed type signature defined by the http-parser lib, with a pointer to a buffer containing the parsed data relevant to the call, so I can't pass in my own variables and solve the problem that way. These functions also return a status code to the http parser, so I can't use the return values either. The suggested way to get data out of the parser for later use is to copy it out to a global variable during the callback - fun with multiple threads.)
Execute the parser on the buffered socket data. At this stage, the parser is expected to call its set up callbacks when it parses different sections of the buffer. The callback is supplied with parsed data relevant to each callback (e.g. BODY segment supplied to body_parsed callback function).
Well, this is where the problem shows. The parser has executed, but I don't have any access to the parsed data. Here is where I would add a new task to the queue with a worker function to store the received body data or another to handle the GET request for previously stored data. These functions would need to be supplied with both the parsed information (POST data or GET url) as well as the accepted socket so that the now delegated work can respond to the request and close the connection.
Of course, the obvious solution to the problem is simply to not use this thread-pool model with asynchronous practices, but I would like to know, for now and for later, how best to tackle this problem.
How can I get the parsed data from these callbacks back to the worker thread function. I've considered simply making my on_url_parsed and on_body_parsed do the rest of the application's job (storing and retrieving data), but of course I no longer have the client's socket to respond back to in these contexts.
If needed, I can post up the source code to the project when I get the chance.
Edit: It turns out that it is possible to access a user defined void * from within the callbacks of this particular http-parser library as the callbacks are passed a reference to the caller (the parser object) which has a user-definable data field.
A well-designed callback interface would provide for you to give the parser a void * which it would pass on to each of the callback functions when it calls them. The callback functions you provide know what type of object it points to (since you provide both the data pointer and the function pointers), so they can cast and properly dereference it. Among other advantages, this way you can provide for the callbacks to access a local variable of the function that initiates the parse, instead of having to rely on global variables.
If the parser library you are using does not have such a feature (and you don't want to switch to a better-designed one), then you can probably use thread-local storage instead of global variables. How exactly you would do that depends on your thread library and compiler, or you could roll your own by using thread identifiers as keys to thread-specific slots in some global data structure (a hash table for instance).

How to write a catch-all Windows hook recipient function?

I want to create a generic, catch-all Windows API (and application function) hook recipient to permit dynamic and safe hooking.
The idea is to:
create and set a hook on the target function which is determined by user at runtime,
then, once it is intercepted, pass the values to a Lua runtime so the user can safely and dynamically inspect the values, or edit
pass control to the original function.
Decoding the function arguments to meaningful values can be left to the Lua script once it has them.
Any hints, tips welcome.
P.S. I am thinking of using mhook2.3

Glade, GtkBuiler or Gtk unexpectedly swapped a signal handler

void
add_button_clicked(GtkButton * widget, GtkTreeView * treeview){
printf("%s\n",G_OBJECT_TYPE_NAME(widget));
} // Prints GtkTreeView
While the standard GtkButton:clicked signal is supposed to work like this (the widget itself followed by the user data) for some reason, the swapped signal handler has been called here and the two parameters are mixed up.
I could just shuffle the code around a bit to get past this but I would like to get to the bottom of why this is happening so I can fix/prevent it.
The glade swap checkbox is unchecked, and I didn't manually connect the signal anywhere, so I don't know why this is happening.
Edit: Ok, now it's happening to ALL my callbacks which is a big huge tremendous problem! Please help!
Edit: This "Feature" is apparently here so glade users can add a glade object to the callback and directly reference a gtk function so that they can for example hide a widget without having to write a single line of code. I'll roll with it.
Glade does this so that when you pass another object you can call a standard gtk function directly on it (Such as closing a window) without needing to write any code at all.

Should a g_object_new have a matching g_object_unref?

I'm using libnotify to show desktop notifications in my application; notify_notification_new() returns a NotifyNotification*, which should be passed as the first param to further function calls of the notification library.
There is no notify_notification_free() which frees the pointer it returns. I looked up the source of notify_notification_new() and internally it does a g_object_new(), gets a GObject* and returns it as a NotfiyNotification*, so when my application does the clean up, should I call a g_object_unref() on the pointer returned by notify_notification_new()?
Yes, unless the reference is "floating". Subclasses of GInitiallyUnowned use floating references; the most common use is GTK widgets.
When you create a GTK widget using a gtk_whatever_new() function, it has one reference which is marked as floating. When you add the widget to a container, the container must also hold a reference to the widget. But instead of calling g_object_ref() on the widget and increasing the reference count to 2, it "sinks" the object's floating reference and turns it into a normal reference. You could say that the container now "owns" the widget.
Then when you destroy the container, it calls g_object_unref() on the widget, and the reference count becomes zero, and the widget is destroyed. That way you're not responsible for destroying it yourself anymore.
So with normal GObjects, which usually don't go into containers, there is no transfer of ownership. You have to unreference them yourself when you're done with them.
The answer is yes, I figured it out from Gnome's page on ownership, I hope it helps someone later.

WPF access GUI from other thread

I am working through the requirement to make a WPF Application single instance only.
However - I have to pass the command line to the first instance and then perform some UI action.
I am using a Mutext to check for already running instances, I do use NamedPipes to transfer the command line to the already running instance.
But of course I am not in the correct Thread to access "Window1".
I tried to store a reference to "Window1" in a static class and then use the Dispatcher to call a Method in "Window1", however, as soon as I try to access a variable (class wide scope in "Window1") I receive a "Object reference not set to an instance of an object."
The UI Action is to add a new Tab to a TabControl - during initialization of the new Tab some work is done - and the variables are initialized and even the method I want to call works during the init - but when called from the Dispatcher it fails.
Any hints, how to do this? Am I on the wrong track here?
Thanks!
This is easy:
void ProcessCommandLine(string commandLine)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
... code to process the command line here ...
});
}
You can call this from your App.Startup and also from your thread that receives messages from the named pipe.
The key considerations here are:
Use of BeginInvoke instead of Invoke to prevent the calling thread from waiting
Use of DispatcherPriority.ApplicationIdle to guarantee the application has finished initializing before the command line is processed
Use of Application.Current.Dispatcher instead of Window1.Dispatcher in case Window1 has not yet been initialzed
That's not right, are you certain that the mutex is passing control correctly to your currently running instance of the application?
If it was a thread UI access issue, you should have received this error: The calling thread cannot access this object because a different thread owns it.
The fact that you're getting an "Object reference not set to an instance of an object." error message means that you've not yet instantiated the object as new.

Resources