
NCI/Utils.pir - Utility functions to make Parrot NCI work easier

# Perl 6:
# Load this library and the NCI wrapper for a framework/toolkit
use NCI::Utils:from<parrot>;
use FooTK:from<parrot>;
sub MAIN(*@ARGS is rw) {
# Call toolkit's init function, overwriting @ARGS with mangled copy
@ARGS = call_toolkit_init(&fooInit, @ARGS, $*PROGRAM_NAME);
# Alternately, you can save both the original @ARGS and mangled copy
my @mangled_args = call_toolkit_init(&fooInit, @ARGS);
# ...
}
# PIR:
.sub main :main
.param pmc argv
# Load this library and the NCI wrapper for a framework/toolkit
load_bytecode 'NCI/Utils.pbc'
load_bytecode 'FooTK.pbc'
# Find Subs for call_toolkit_init() and the toolkit's init function
.local pmc call_toolkit_init, fooInit
call_toolkit_init = get_global ['NCI';'Utils'], 'call_toolkit_init'
fooInit = get_global ['FooTK'], 'fooInit'
# Call toolkit's init function, overwriting argv with mangled copy
argv = call_toolkit_init(fooInit, argv)
# Alternately, you can save both the original argv and mangled copy
.local pmc mangled_argv
mangled_argv = call_toolkit_init(fooInit, argv)
# ...
.end

Some Parrot NCI coding tasks are relatively common, but usually result in a relatively grotty bit of code that no one should have to write twice. Hence this library, which provides utilities to handle these common tasks more cleanly (or at least collect all the grotty code in one place).
Currently, there is just one such utility implemented:
Call an NCI void function with params (&argc, argv) (and thus having Parrot signature 'v3p'). This is a very common signature for toolkit (AKA framework) init functions that want to filter out command line options that the toolkit itself should process. Since it is expected that the init call will remove some arguments, call_toolkit_init returns an updated argv. orig_argv is never changed; the NCI call is performed using a copy. When calling from an HLL that removes the program name from argv automatically, provide the program_name argument so that call_toolkit_init() can adjust argv alignment internally; this will tend to make the toolkit init function much happier.
Wraps an NCI function in a closure which translates between Parrot's strings and C's asciiz strings. Any number (including 0) of argument indices are accepted. The magic index value of -1 indicates that the return value should be translated.
Emulates dlfunc op, but extends this to provide functionality for more complex, but common, types. Current supported types are:
Translate Parrot strings to C asciiz strings and back. Argument strings belong to Parrot and are freed after the call. Return strings belong to the C library and are not freed by Parrot.
Create a NCI function by looking up name in library, assuming a calling signature of signature. The supported types of signature are: p = pmc i = int f = float t = null-terminated array of char ...