|
The PREINIT: keyword allows extra variables to be declared immediately before or after the
declarations of the parameters from the INPUT: section are emitted.
If a variable is declared inside a CODE: section it will follow any typemap code that is
emitted for the input parameters. This may result in the declaration ending up after C code,
which is C syntax error. Similar errors may happen with an explicit ;-type or +-type
initialization of parameters is used (see "Initializing
Function Parameters"). Declaring these variables in an INIT: section will not help.
In such cases, to force an additional variable to be declared together with declarations of
other variables, place the declaration into a PREINIT: section. The PREINIT: keyword may be
used one or more times within an XSUB.
The following examples are equivalent, but if the code is using complex typemaps then the
first example is safer.
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
PREINIT:
char *host = "localhost";
CODE:
RETVAL = rpcb_gettime( host, &timep );
OUTPUT:
timep
RETVAL
|
|
For this particular case an INIT: keyword would generate the same C code as the PREINIT:
keyword. Another correct, but error-prone example:
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
CODE:
char *host = "localhost";
RETVAL = rpcb_gettime( host, &timep );
OUTPUT:
timep
RETVAL
|
|
Another way to declare host is to use a C block in the CODE: section:
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
CODE:
{
char *host = "localhost";
RETVAL = rpcb_gettime( host, &timep );
}
OUTPUT:
timep
RETVAL
|
|
The ability to put additional declarations before the typemap entries are processed is very
handy in the cases when typemap conversions manipulate some global state:
MyObject
mutate(o)
PREINIT:
MyState st = global_state;
INPUT:
MyObject o;
CLEANUP:
reset_to(global_state, st);
|
|
Here we suppose that conversion to MyObject in the INPUT: section and from
MyObject when processing RETVAL will modify a global variable global_state. After
these conversions are performed, we restore the old value of global_state (to
avoid memory leaks, for example).
There is another way to trade clarity for compactness: INPUT sections allow declaration of
C variables which do not appear in the parameter list of a subroutine. Thus the above code for
mutate() can be rewritten as
MyObject
mutate(o)
MyState st = global_state;
MyObject o;
CLEANUP:
reset_to(global_state, st);
|
|
and the code for rpcb_gettime() can be rewritten as
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
char *host = "localhost";
C_ARGS:
host, &timep
OUTPUT:
timep
RETVAL
|
|
|