Type-safe G_CALLBACK



Hey,

Is there any reason we don't have something similar to
G_DEFINE_CALLBACK() as described below in [1]? It seems like it would
increase type-safety a lot...

Thanks,
David

[1] : See [2] for compiler output

#include <gio/gio.h>

/**
 * G_DEFINE_CALLBACK:
 * @function: The function to check
 * @function_type: The expected type of @function.
 *
 * Helper macro to define type-safe callback macros on modern
 * compilers. On older compilers, this just uses the generic
 * G_CALLBACK() macro.
 *
 * In addition to using this for all callback functions, you should
 * use this for every signal in a type. For example, for the
 * #GVolumeMonitor::drive-connected signal it would be used this way
 *
 * <programlisting>
 * #define G_VOLUME_MONITOR_DRIVE_CONNECTED_CALLBACK(f,
user_data_type) (G_DEFINE_CALLBACK(f, void (*)(GVolumeMonitor*,
GDrive*, user_data_type)))
 * </programlisting>
 *
 * so the user can use to define a callback for the signal
 *
 * <programlisting>
 * g_signal_connect (volume_monitor,
 *                   "drive-connected",
 *                   G_VOLUME_MONITOR_DRIVE_CONNECTED_CALLBACK
(on_drive_connected, gpointer),
 *                   NULL);
 * </programlisting>
 *
 * and get a compile-time warning if the on_drive_connected() callback
 * is not of the right type.
 *
 * Since: 2.30
 */
#if __GNUC__ >= 4
#  define G_DEFINE_CALLBACK(function, function_type)
(__builtin_choose_expr (__builtin_types_compatible_p (typeof
(&function), function_type), G_CALLBACK (function), function))
#else /* __GNUC__ >= 4 */
#  define G_DEFINE_CALLBACK(functoin, function_type) G_CALLBACK (function)
#endif /* __GNUC__ >= 4 */


#define G_VOLUME_MONITOR_DRIVE_CONNECTED_CALLBACK(function,
user_data_type) (G_DEFINE_CALLBACK(function, void (*)(GVolumeMonitor*,
GDrive*, user_data_type)))

static void
on_drive_connected (GVolumeMonitor  *monitor,
                    GDrive          *drive,
                    gpointer         user_data)
{
}

static void
on_drive_connected_wrong_type (GVolumeMonitor  *monitor,
                               GDrive          *drive,
                               gint             foo,
                               gpointer         user_data)
{
}

int
main (int argc, char *argv[])
{
  GVolumeMonitor *monitor;

  g_type_init ();

  monitor = g_volume_monitor_get ();
  g_signal_connect (monitor,
                    "drive-connected",
                    G_VOLUME_MONITOR_DRIVE_CONNECTED_CALLBACK
(on_drive_connected, gpointer),
                    NULL);

  g_signal_connect (monitor,
                    "drive-connected",
                    G_VOLUME_MONITOR_DRIVE_CONNECTED_CALLBACK
(on_drive_connected_wrong_type, gpointer),
                    NULL);

  return 0;
}

[2] : Compiler output from compiling the program in [1] - this is with
gcc version 4.6.0 20110315 (Red Hat 4.6.0-0.13) (GCC) from Fedora 15

  gcc -o foo foo.c `pkg-config --cflags --libs gio-2.0`
  foo.c: In function â??mainâ??:
  foo.c:72:3: warning: passing argument 3 of
â??g_signal_connect_dataâ?? from incompatible pointer type [enabled by
default]
  /usr/include/glib-2.0/gobject/gsignal.h:350:9: note: expected
â??GCallbackâ?? but argument is of type â??void (*)(struct
GVolumeMonitor *, struct GDrive *, gint,  void *)â??

As you can see the compiler complains about callbacks, in this case
on_drive_connected_wrong_type(), being the wrong type...


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]