I've been wondering
how function pointers get passed around inside the GObject framework. Some example code seems to play fast and loose with function pointer types, relying on the fact that C's Undefined Behaviour can also include doing what one hopes.
After some source-diving I finally found how GLib calls the callback. It does it through a function pointer of this type in one example:
typedef void (*GMarshalFunc_VOID__UINT_POINTER) (gpointer instance,
guint arg_0,
gpointer arg_1,
gpointer data);
That's for a signal handler whose signature is
void ()(gpointer instance, guint x, gpointer userdata)
.
Because
GtkCellRendererText *
and
void *
are not compatible types, it's actually wrong (it invokes undefined behaviour) to simply copy the signal handler signatures from the
GTK+ documentation!
For this example, the correct function declaration would have to be:
void user_function(gpointer renderer,
gpointer path,
gpointer new_text,
gpointer user_data);
I'm not sure if I want to be that pure. Too much boilerplate type conversion code. Maybe the reasonable compromise is to continue using pointers to specific types, but to make sure that at least the
number of arguments matches what the marshaller functions demand. I think it's far more likely that a C implementation will be sensitive to a mismatched number of arguments (consider how
cdecl
vs
pascal
calling convention specifiers in some compilers determine a function's activation record) than that
void *
will have a different representation than
GtkCellRendererText *
.
No comments:
Post a Comment