fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / docs / pdds / draft / pdd16_native_call.pod
blob2a8b4388fcd1cdedab71710932e731fd02cf038e
1 # Copyright (C) 2001-2010, Parrot Foundation.
2 # $Id$
4 =head1 [DRAFT] PDD 16: Native Call Interface (NCI)
6 =head2 Abstract
8 This PDD describes the native call interface, and the function signatures used
9 to describe those functions.
11 =head2 Version
13 $Revision$
15 =head2 Description
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.
39 =head2 Implementation
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
50 symbols.
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.
56 =over 4
58 =item v
60 Void. As a return type it indicates that there I<is> no return type.
62 Not valid as a parameter type.
64 =item c
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'
68 works.
70 =item s
72 short. An integer type, taken from or put into an I register. It is always
73 signed, not unsigned.
75 =item i
77 int. An integer type. It is always signed, not unsigned.
79 =item l
81 long. An integer type. You know the drill. It is always signed, not unsigned.
83 =item f
85 float. F register denizen.
87 =item d
89 double. F register, double-precision floating point type
91 =item P
93 A PMC register.
95 =item p
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
102 I<no> management of.
104 =item 2
106 A pointer to a short, taken from an P register of an int-like PMC.
108 =item 3
110 A pointer to an int, taken from an P register of an int-like PMC.
112 =item 4
114 A pointer to a long, taken from an P register of an int-like PMC.
116 =item t
118 string pointer. Taken from, or stuck into, a string register. (Converted to a
119 null-terminated C string before passing in)
121 =item U
123 This parameter is used for passing user data to a callback creation. More
124 explanation in the L<callbacks> section.
126 =back
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:
139   /* foo.c */
141   /* specify the function prototype */
142   #ifdef __WIN32
143   __declspec(dllexport) void foo(void);
144   #else
145   void foo(void);
146   #endif
148   void foo(void) {
149     printf("Hello Parrot!\n");
150   }
152 Then, after having compiled the file as a shared library, the PIR code looks
153 like this:
155   .sub main :main
156      .local pmc lib, func
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"
165      # invoke
166      func()
168   .end
171 =head3 Callbacks
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
177 what should be done.
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
183 callback uses.
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
213 NCI function.
215 The signature of the I<parrot> subroutine which is called by the callback
216 should be:
218    void parrotsub(PMC user_data, <type> external_data)
220 The sequence for this is:
222 =over 4
224 =item Step 1
226 Create a callback function.
228   new_callback CB_PMC, CB_SUB, USER_DATA, "signature"
230 =item Step 2
232 Register the callback
234   dlfunc C_FUNCTION, "function_name", "signature"
235   C_FUNCTION(CP_PMC, USER_DATA)
237 =back
239 When the callback function is invoked by the external library, the function
240 itself should look like:
242 =begin PIR
244   .sub _my_callback
245     .param pmc my_data
246     .param pmc library_data   # type depends on signature
247     # Do something with the passed in data
248   .end
250 =end PIR
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.
261 =begin PIR
263   .sub main
265     # set up callback
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
271     userdata = 42
273     .local pmc callback_sub
274     callback_sub = new_callback sub, userdata, "vtU"
276     # set up NCI
278     .local pmc lib, fun
279     lib = loadlib "hello"
280     fun = dlfunc lib, "sayhello", "vpP"
282     # do the NCI call, foo_callback is invoked from C
283     fun()
285   .end
287   .sub foo_callback
288     .param pmc result
289     .param pmc udata
290     print "Foo callback\n"
291   .end
293 =end PIR
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
298 to be known.
300   #include <stdio.h>
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*);
306   #ifdef __WIN32
307   __declspec(dllexport) void sayhello(callbackfun cb, void *userdata);
308   #else
309   void sayhello(callbackfun cb, void *userdata);
310   #endif
312   void sayhello(callbackfun cb, void* userdata) {
313       const char *result = "succeeded";
315       /* invoke the callback synchronously */
316       cb(result, userdata);
317   }
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.)
322 =head2 References
324 F<pdd06_pasm.pod>
326 =head2 See Also
328 F<t/pmc/nci.t>, F<src/nci_test.c>
330 =cut
332 __END__
333 Local Variables:
334   fill-column:78
335 End:
336 vim: expandtab shiftwidth=4: