1 # Copyright (C) 2001-2010, Parrot Foundation.
4 =head1 [DRAFT] PDD 16: Native Call Interface (NCI)
8 This PDD describes the native call interface, and the function signatures used
9 to describe those functions.
17 The NCI is designed to allow Parrot to interface to I<most> of the functions
18 in a C library without having to write any C code for that interface. It
19 isn't designed to be a universal C-less interface--there will always be
20 libraries that have some bizarre parameter list that requires that some C be
21 written. It should, however, handle all the simple cases.
23 Using the NCI, parrot automatically wraps the C functions and presents them
24 as prototyped subroutines that follow normal parrot calling conventions, and
25 can be called like any other parrot subroutine.
27 The NCI uses the platform native dynamic by-name function loading mechanism
28 (dlopen/dlsym on unix and LoadLibrary/GetProcAddress on Win32, for example)
29 to get the function pointer, then dynamically generates the wrapper based on
30 the signature of that function.
32 As there is no good platform-independent way to determine function
33 signatures (C header files are not always available (certainly not for
34 libraries not designed for access from C) and not always reasonably
35 parseable anyway, and there is no generic way to query a function for its
36 signature) the signature must be passed in when the linkage between the C
37 function and parrot is made.
41 =head3 Function signatures
43 The following list are the valid symbols in the function signatures for
44 Parrot's NCI. Note that only letters and numbers are valid, and each symbol
45 represents a single parameter passed into the NCI. Note that the symbols are
46 case-sensitive, and must be within the base 7-bit ASCII character set.
48 At some point punctuation may be used as modifiers on the function
49 parameters, in which case each parameter may be represented by multiple
52 In I<no> case should the signature symbols be separated by whitespace. This
53 restriction may be lifted in the future, but for now remains as an avenue
54 for adding additional functionality.
60 Void. As a return type it indicates that there I<is> no return type.
62 Not valid as a parameter type.
66 Char. This is an integer type, taken from (or put into) an I register. NOTE:
67 it might be signed or unsigned because that is how an unadorned C 'char'
72 short. An integer type, taken from or put into an I register. It is always
77 int. An integer type. It is always signed, not unsigned.
81 long. An integer type. You know the drill. It is always signed, not unsigned.
85 float. F register denizen.
89 double. F register, double-precision floating point type
97 PMC thingie. A generic pointer, taken from a PMC by using its
98 get_pointer vtable function, or NULL for a PMCNULL.
99 If this is a return type and the value is NULL, PMCNULL is returned,
100 otherwise parrot will create a new UnManagedStruct PMC type, which
101 is just a generic "pointer to something" PMC type which Parrot does
106 A pointer to a short, taken from an P register of an int-like PMC.
110 A pointer to an int, taken from an P register of an int-like PMC.
114 A pointer to a long, taken from an P register of an int-like PMC.
118 string pointer. Taken from, or stuck into, a string register. (Converted to a
119 null-terminated C string before passing in)
123 This parameter is used for passing user data to a callback creation. More
124 explanation in the L<callbacks> section.
128 Note that not all types are valid as return types.
130 =head3 Example NCI call
132 This section describes the simplest example for NCI possible. To every NCI
133 invocation, there are two parts: the native function to be invoked, and the
134 PIR code to do the invocation.
136 First the native function, to be written in C. On Windows, it is necessary
137 to do a DLL export specification of the NCI function:
141 /* specify the function prototype */
143 __declspec(dllexport) void foo(void);
149 printf("Hello Parrot!\n");
152 Then, after having compiled the file as a shared library, the PIR code looks
158 # load the shared library
159 lib = loadlib "hello" # no extension, .so or .dll is assumed
161 # get a reference to the function from the library just
162 # loaded, called "foo", and signature "void" (and no arguments)
163 func = dlfunc lib, "foo", "v"
173 Some libraries, particularly ones implementing more complex functionality such
174 as databases or GUIs, want callbacks, that is ways to call a function under
175 the control of the library rather than under control of the interpreter. These
176 functions must be C functions, and generally are passed parameters to indicate
179 Unfortunately there's no good way to generically describe all possible
180 callback parameter sets, so in some cases hand-written C will be necessary.
181 However, many callback functions share a common signature, and parrot provides
182 some ready-made functions for this purpose that should serve for most of the
185 There are two callback functions, Parrot_callback_C and Parrot_callback_D,
186 which differ if the passed in C<user_data> is second or first respectively:
188 void (function *)(void *library_data, void *user_data);
190 void (function *)(void *user_data, void *library_data);
192 The information C<library_data> is normally coming from C code and can be
193 any C type that Parrot supports as NCI value.
195 The position of the C<user_data> is specified with the C<U> function
196 signature, when creating the callback PMC:
198 cb_PMC = new_callback cb_Sub, user_data, "tU"
200 Given a Parrot function C<cb_Sub>, and a C<user_data> PMC, this creates a
201 callback PMC C<cb_PMC>, which expects the user data as the second argument.
202 The information returned by the callback (C<library_data>) is a C string.
204 Since parrot needs more than just a pointer to a generic function to figure
205 out what to do, it stuffs all the extra information into the C<user_data>
206 pointer, which contains a custom PMC holding all the information that Parrot
207 needs. This also implies that the C function that installs the callback,
208 must not make any assumptions on the C<user_data> argument. This argument
209 must be handled transparently by the C code.
211 The callback function takes care of wrapping the external data pointer into
212 an UnManagedStruct PMC, the same as if it were a p return type of a normal
215 The signature of the I<parrot> subroutine which is called by the callback
218 void parrotsub(PMC user_data, <type> external_data)
220 The sequence for this is:
226 Create a callback function.
228 new_callback CB_PMC, CB_SUB, USER_DATA, "signature"
232 Register the callback
234 dlfunc C_FUNCTION, "function_name", "signature"
235 C_FUNCTION(CP_PMC, USER_DATA)
239 When the callback function is invoked by the external library, the function
240 itself should look like:
246 .param pmc library_data # type depends on signature
247 # Do something with the passed in data
252 Parrot itself handles all the nasty bits involved in collecting up the
253 interpreter pointer, creating the wrapping PMCs, stuffing data various places,
254 and generally dealing with the bookkeeping.
256 =head3 Example Callback
258 This section contains an example to register a callback function and have
259 it call back into Parrot.
267 .local pmc sub, userdata
268 sub = get_global "foo_callback" # get the sub to act as a callback sub
270 userdata = new 'Integer' # set up some userdata
273 .local pmc callback_sub
274 callback_sub = new_callback sub, userdata, "vtU"
279 lib = loadlib "hello"
280 fun = dlfunc lib, "sayhello", "vpP"
282 # do the NCI call, foo_callback is invoked from C
290 print "Foo callback\n"
295 The C code contains the function to be invoked through NCI. In the function
296 C<sayhello> a function call is done to a Parrot subroutine. The C<sayhello>
297 function gets a reference to this callback function, so its signature needs
301 #include <parrot/parrot.h>
303 /* declare the function signature of the Parrot sub that will be invoked */
304 typedef void (*callbackfun)(const char*, void*);
307 __declspec(dllexport) void sayhello(callbackfun cb, void *userdata);
309 void sayhello(callbackfun cb, void *userdata);
312 void sayhello(callbackfun cb, void* userdata) {
313 const char *result = "succeeded";
315 /* invoke the callback synchronously */
316 cb(result, userdata);
319 The file containing this C code should be compiled as a shared library
320 (specifying the C<include> directory so F<parrot/parrot.h> can be found.)
328 F<t/pmc/nci.t>, F<src/nci_test.c>
336 vim: expandtab shiftwidth=4: