Re: Type-safe G_CALLBACK



For type-safety and light callback, someone may be interesting about this.

Once a time, I worked out a prototype when I need the signal-slot
mechanism in my embedded environment.Please take a look at
https://code.google.com/p/c-sigslot/downloads/list.

The implementation is based on standard longjmp and "stack-frame copy"
technical. So it's 100% type-safety and no marshal needed.

Although it is not 100% portable, I think it works on most stack-based
system. Since there are just a few lines of assemble code for
perticular circumstances, it is easy to port to a special system. The
unknown compiler implemention is pure ANSI C compliant, but it is
based on a hack inside the jmpbuf structure. The comptibility can be
improved by the posix setcontext/getcontext specification.

It is not suitable for large project since you should specify a enough size
of stack-frame for each function or each compilation unit(on header of
the C source file), or a enough size for global scope. I think it can
be eliminated through a modification of the compiler.

The invoke interface can also be improved if C99 variadic macros
present, so that we can use a unified SIGNAL(...) declaration instead
of SIGNAL1(v1), SIGNAL2(v1, v2), etc.

All of the work I would like to accomplish if I have enough time.
Nowadays I'm working hard to port the Tristan's GtkCellArea
implementation to gtk+ 2.x, to make it running under my old
framebuffer base system. I also want to make a framebuffer backend for
the new GTK. I feel a little sorry for that there are few chinese
afford in public community since we have to struggle for better living
and fight against our companions day after day.

2011/3/18 David Zeuthen <zeuthen gmail com>:
> 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...
> _______________________________________________
> gtk-devel-list mailing list
> gtk-devel-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-devel-list
>


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