Re: [gtk-list] Marshallers, _interp, and the Meaning of Life

On Tue, 10 Feb 1998, Jay Bloodworth wrote:

> I (and others, I imagine) would find it very helpful if someone could give
> a nice, concise explanation of signal marshallers: what they are, why we
> need them, etc.  This might also make a fine addition to the tutorial.

first, you don't need to deal with marshalling if you don't write language
bindings for the toolkit or you are not adding signals to a widget.

any object in gtk can introduce certain signals that will be inherited.
it is up to the object to define a certain function signature for this signal.
e.g. the move_resize signal of the GtkWindowClass:

  gint (* move_resize) (GtkWindow *window,
                        gint      *x,
                        gint      *y,
                        gint       width,
                        gint       height);

if the move_resize signal is emitted for a GtkWindow, the corresponding
class function (the function that GtkWIndowClass.move_resize points to),
will be invoked accrding to the signals signature.

when the GtkWindowClass first announces the move_resize signal, it also
provids the signals signature:

>     gtk_signal_new ("move_resize",
>                     GTK_RUN_LAST,
>                     object_class->type,
>                     GTK_SIGNAL_OFFSET (GtkWindowClass, move_resize),
>                     gtk_window_marshal_signal_1,
   signal marshaller--^
>                     GTK_TYPE_BOOL, 4,
       return value---^		     ^-- number of function arguments
>                     GTK_TYPE_POINTER, GTK_TYPE_POINTER,
  argument x (gint*)--^			^-- argument y (gint*)
>                     GTK_TYPE_INT, GTK_TYPE_INT);
argument width (gint)-^             ^- argument height (gint)

for the invokation (in C), the called function expects the arguments
height,width,*y,*x,*window on the stack (in this order).
since there is no way (in plain C) to push arguments onto the stack at
will (depending on the signals signature) without using e.g. compiler
internal functions (because function signatures in C are statically typed,
with the excetption of the ellipsis operator "..."), there needs to be a
portable and consistent way to provide the arguments to a called function.
this job is done by the marshaller functions, at the cost of an additional
function call per signal handler invocation.
first, the signal signature for the move_resize signal of a GtkWindowClass:

typedef gint (*GtkWindowSignal1) (GtkObject *object,
                                  gpointer   arg1,
                                  gpointer   arg2,
                                  gint       arg3,
                                  gint       arg4,
                                  gpointer   data);

and then the marshaller function:

static void
gtk_window_marshal_signal_1 (GtkObject      *object,
                             GtkSignalFunc   func,
                             gpointer        func_data,
                             GtkArg         *args)
  GtkWindowSignal1 rfunc;
  gint *return_val;

  rfunc = (GtkWindowSignal1) func;
  return_val = GTK_RETLOC_BOOL (args[4]);

  *return_val = (* rfunc) (object,
                           GTK_VALUE_POINTER (args[0]),
                           GTK_VALUE_POINTER (args[1]),
                           GTK_VALUE_INT (args[2]),
                           GTK_VALUE_INT (args[3]),

the signal arguments are passed on to the marshaller function via a
dynamic array, and the marshaller puts them onto the stack according
to the signal signature when calling the signal handler rfunc.
so all marshaller functions have the same signature, they get the actual
object pointer, the signal handler its func_data argument, plus the signal
arguments passed in the same way. their only job is to push/pop these
arguments onto the stack in the correct order for the signal handlers

in this specific case, the marshaller will call
static gint
gtk_real_window_move_resize (GtkWindow *window,
                             gint      *x,
                             gint      *y,
                             gint       width,
                             gint       height)

which without marshalling would have looked like
static void
gtk_real_window_move_resize (GtkObject      *object,
                             gpointer        func_data,
                             GtkArg         *args)
  gint *x;
  gint *y;
  gint width;
  gint height;
  gint *return_val;
  return_val = GTK_RETLOC_BOOL (args[4]);
  x = GTK_VALUE_POINTER (args[0]);
  y = GTK_VALUE_POINTER (args[1]);
  width = GTK_VALUE_INT (args[2]);
  height = GTK_VALUE_INT (args[3]);
  *return_val = something_that_came_out_of_the_function;

hm, hope i haven lost you, marshalling itself is for sure not one of the most
exciting toolkit features ;), but it presents the nice possibility to have
function signatures depending on the signal types.

> Jay


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