A typical marshaller skeleton will look like this:
static void
some_custom_marshaler (GClosure * closure,
GValue * return_value,
guint n_param_values,
const GValue * param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
dGPERL_CLOSURE_MARSHAL_ARGS;
GPERL_CLOSURE_MARSHAL_INIT (closure, marshal_data);
PERL_UNUSED_VAR (return_value);
PERL_UNUSED_VAR (n_param_values);
PERL_UNUSED_VAR (invocation_hint);
ENTER;
SAVETMPS;
PUSHMARK (SP);
GPERL_CLOSURE_MARSHAL_PUSH_INSTANCE (param_values);
/*
* push more parameters onto the perl stack... the ones
* in which we are interested are param_values[1] through
* param_values[n_param_values-1], because the 0th one
* has been handled for us.
*/
GPERL_CLOSURE_MARSHAL_PUSH_DATA;
PUTBACK;
/* this example invokes the callback in array context.
* other options are G_DISCARD and G_SCALAR. see C<call_sv>
* in L<perlcall>. */
GPERL_CLOSURE_MARSHAL_CALL (G_ARRAY);
/*
* get return values, if needed, and clean up.
* "count" will contain the number of values returned on the
* stack.
*/
FREETMPS;
LEAVE;
}
- dGPERL_CLOSURE_MARSHAL_ARGS
-
Declare several stack variables that the various GPERL_CLOSURE_MARSHAL macros will need. Declares
SV ** sp
for you. This must go near the top of your C function, before any code statements. - GPERL_CLOSURE_MARSHAL_INIT (closure, marshal_data)
-
This must be called as the first non-declaration statement in the marshaller function. In a threaded/threadable Perl, this ensures that all Perl API calls within the function happen in the same Perl interpreter that created the callback; if this is not first, strange things will happen. This statement also initalizes
pc
(the perl closure object) on the stack. - GPERL_CLOSURE_MARSHAL_PUSH_INSTANCE(param_values)
-
This pushes the callback's instance (first parameter) onto the Perl argument stack, with XPUSHs. Handles the case of swapped instance and data. param_values is the array of GValues passed into your marshaller. Note that the instance comes from param_values[0], so you needn't worry about that one when putting the rest of the parameters on the arg stack.
This assumes that n_param_values > 1.
- GPERL_CLOSURE_MARSHAL_PUSH_DATA
-
Push the callback's user data onto the Perl arg stack, with XPUSHs. Handles the case of swapped instance and data. The user data is not included in param_values.
- GPERL_CLOSURE_MARSHAL_CALL(flags)
-
Invoke the callback. You must ensure that all the arguments are already on the stack, and that you've called PUTBACK. This will invoke call_sv(), adding G_EVAL to the flags you supply, and store the return value in count on the stack (count is declared by
dGPERL_CLOSURE_MARSHAL_ARGS
). It then refreshes the stack pointer. If an exception occurred, the function returns after running exception handlers.You'll be interested in the following values for flags:
G_DISCARD this is effectively "void return", as it discards whatever the callback put on the return stack. G_SCALAR invoke the callback in scalar context. you are pretty much guaranteed that one item will be on the stack, even if it is undef. G_ARRAY invoke the callback in array context. C<count> (declared by C<dGPERL_CLOSURE_MARSHAL_ARGS>) will contain the number of items on the return stack.
As the callback is always run with G_EVAL, call_sv() will clobber ERRSV ($@); since closures are typically part of a mechanism that is transparent to the layer of Perl code that calls them, we save and restore ERRSV. Thus, code like
eval { something that fails } $button->clicked; # $@ still has value from eval above
works as expected.
See
call_sv
in perlcall for more information. - dGPERL_CALLBACK_MARSHAL_SP
-
Declare the stack pointer such that it can be properly initialized by
GPERL_CALLBACK_MARSHAL_INIT
. Do not just usedSP
. This should always come last in a list of declarations as its expansion might contain statements under certain conditions. - GPERL_CALLBACK_MARSHAL_INIT(callback)
-
Initialize the callback stuff. This must happen before any other Perl API statements in the callback marshaller. In a threaded Perl, this ensures that the proper interpreter context is used; if this isn't first, you'll mix and match two contexts and bad things will happen.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 70:
'=item' outside of any '=over'
=over without closing =back