I'm repeatedly bumping into the problem of setting up signal handlers in GTK+ code, not needing several of the parameters and tempted to use the same function as the handler for several signals, whose handlers have different signatures - but with the first N arguments (the ones I care about) the same.
Is it safe (in the sense that it isn't undefined behaviour, rather than the more pragmatic sense of "does it work on my PC?") to pass pointers to functions to the GObject API when those functions expect fewer arguments than they will actually get from the signal emission process?
Or, to divorce this from GTK+, is this code okay?
/* Note: No void *userdata argument! */
void show(int x) {
printf("x = %d\n", x);
}
void do_stuff(void (*fn)(int, void *), void *userdata) {
static int total = 0;
(*fn)(total, userdata);
total++;
}
void doitnow(void) {
do_stuff(&show, NULL);
}
For extra credit, discuss the implications of different return value types between function signature and call site.
Edit: An almost-identical question probes "compatible function type" more closely, and draws an answer directly addressing my concrete problem - that of chaining GObject signal handlers. TL;DR: Yes, it's undefined behaviour, but it's practically idiomatic (though not obligatory) in some toolkits.
(*fn)
in do_stuff. Just callfn(total, userdata)
. Sincefn
is a function pointer, the function call operator(total, userdata)
does exactly what you expect. – Tannie