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; }
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.
SV ** sp
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.
pc
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.
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.
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.
dGPERL_CLOSURE_MARSHAL_ARGS
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.
call_sv
Declare the stack pointer such that it can be properly initialized by GPERL_CALLBACK_MARSHAL_INIT. Do not just use dSP. This should always come last in a list of declarations as its expansion might contain statements under certain conditions.
GPERL_CALLBACK_MARSHAL_INIT
dSP
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:
'=item' outside of any '=over'
=over without closing =back
To install Glib, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Glib
CPAN shell
perl -MCPAN -e shell install Glib
For more information on module installation, please visit the detailed CPAN module installation guide.