source: project/wiki/eggref/4/lazy-ffi @ 12880

Last change on this file since 12880 was 12880, checked in by sjamaan, 12 years ago

Temporary hack to fix example sections in wiki eggdoc pages

File size: 8.8 KB
Line 
1[[tags: egg]]
2
3== lazy-ffi
4
5[[toc:]]
6
7=== Description
8
9Another foreign function interface, based on libffi.
10
11=== Author
12
13[[felix winkelmann]]
14
15=== Requirements
16
17* [[silex]]
18* [[easyffi]]
19
20=== Download
21
22[[http://www.call-with-current-continuation.org/eggs/lazy-ffi.egg|lazy-ffi.egg]]
23
24=== Usage
25
26{{(require-extension lazy-ffi)}}
27
28This extension defines the module {{lazy-ffi}}.
29
30=== Documentation
31
32A very easy to use foreign function interface, which provides a
33special read-syntax to call arbitrary functions in shared
34libraries. This facility uses
35[[http://sources.redhat.com/libffi|libffi]] and dynamic loading (via
36{{dlopen(3)}}) to load shared libraries and construct foreign calls at
37runtime and in interpreted code.
38
39To use this extension in compiled code, invoke the compiler with
40{{-extension lazy-ffi}}.  This is necessary because the extension
41defines a special read-syntax which has to be registered before the
42source code is read in. This is not required for interpreted code.
43
44Note: the libffi package is actively under development, but the
45website doesn't reflect the current work in progress. A snapshot of
46the current development version is available at
47[[http://www.call-with-current-continuation.org/libffi-2.tgz]]. The
48latter is more portable and robust than the version currently
49advertised at the libffi website.
50
51==== Read syntax
52
53The following read syntax is provided:
54
55<read>#~STRING</read>
56
57Registers the shared library named STRING. Subsequent access to
58foreign symbols will try to find the required symbol in all libraries
59registered so far. The library name may also be {{#f}}, which allows
60looking up symbols in the current executable (this may require special
61linker options, depending on platform).
62
63<read>#~SYMBOL</read>
64
65Identifies a foreign symbol, which will be looked up in the currently
66registered shared libraries.  Returns a procedure that can be called
67like a normal Scheme procedure.
68
69A special case is the syntax {{#~~}}. When used, an expression is
70expected preceding any further arguments that should evaluate to a
71foreign pointer object identifying the address of a C function.
72
73<read>#~(ITEM ...)</read>
74
75Equivalent to {{(list #~ITEM ...)}}. This can be used to register
76several shared libraries at once or pre-resolve foreign symbols.
77
78A foreign procedure is called like a normal procedure, with argument
79values automatically converted to the appropriate foreign
80representation, using the following mapping of Scheme types to C
81types:
82
83<table>
84<tr><th>Scheme type</th><th>C type</th></tr>
85<tr><td>boolean</td><td>{{int}} (1 or 0)</td></tr>
86<tr><td>exact</td><td>{{int}}</td></tr>
87<tr><td>inexact</td><td>{{double}}</td></tr>
88<tr><td>char</td><td>{{char}}</td></tr>
89<tr><td>pointer or locative</td><td>{{void *}}</td></tr>
90<tr><td>string</td><td>{{char *}}</td></tr>
91<tr><td>symbol</td><td>{{char *}}</td></tr>
92</table>
93
94Arguments of any other type will signal an error (see below for
95specifying specific argument conversions).
96
97Additionally, the procedure can be called with a number of special
98keyword arguments:
99
100; {{return}} : {{TYPE}}
101
102Specifies the result type. If not given, the result will be ignored. TYPE should be one of the following:
103
104<table>
105<tr><td>{{int:}}</td></tr>
106<tr><td>{{char:}}</td></tr>
107<tr><td>{{float:}}</td></tr>
108<tr><td>{{double:}}</td></tr>
109<tr><td>{{pointer:}}</td></tr>
110<tr><td>{{string:}}</td></tr>
111<tr><td>{{symbol:}}</td></tr>
112<tr><td>{{bool:}}</td></tr>
113<tr><td>{{void:}}</td></tr>
114<tr><td>{{scheme-object:}}</td></tr>
115</table>
116
117; {{safe}} : {{BOOLEAN}}
118
119If given, then the call may call back into Scheme (for example by
120passing a pointer to a callback function).  If not given, then call
121may '''not''' invoke any Scheme callbacks, or bad things will happen.
122
123{{TYPE VALUE}}
124
125To force a specific argument type conversion (and to allow slightly
126better argument type checking), a type specifier may also be provided
127as a keyword, followed by the actual argument. Valid type specifiers
128are:
129
130<table>
131<tr><td>{{int:}}</td><td>exact number</td></tr>
132<tr><td>{{float: double:}}</td><td>inexact number</td></tr>
133<tr><td>{{pointer:}}</td><td>pointer object</td></tr>
134<tr><td>{{bool:}}</td><td>boolean (actually any Scheme object), will be passed as 1 or 0</td></tr>
135<tr><td>{{char:}}</td><td>char</td></tr>
136<tr><td>{{string:}}</td><td>string</td></tr>
137<tr><td>{{symbol:}}</td><td>string (the name of the symbol)</td></tr>
138<tr><td>{{scheme-object:}}</td><td>any Scheme value</td></tr>
139<tr><td>{{scheme-pointer:}}</td><td>any non-immediate Scheme value (a pointer to the data-section will be passed)</td></tr>
140</table>
141
142(The type specifiers {{scheme-pointer:}} and {{scheme-object:}} are
143mainly intended for advanced uses of this extension)
144
145=== Examples
146
147<examples><example>
148<expr>
149#~"libc.so.6"
150(#~printf "%d -> %g, ok: %s\n" 123 45.67 "hello")
151(#~sleep 1)
152
153#~"libm.so.6"
154
155(#~sin 33.4 return: double:)    ==> 0.915809602890819
156(#~tolower #\A return: char:)   ==> #\a
157
158(let* ([box (f64vector 0)]
159       [r (#~modf 123.456 box return: double:)] )
160  (list r box) )   ==> (0.456 #f64(123.0))
161</expr>
162</example></examples>
163
164Here the "Hello, world" example from the GTK 2.0 tutorial:
165
166<examples><example>
167<expr>
168;; Compile like this:
169;
170; $ csc -X lazy-ffi.scm gtkhello.scm
171
172(use lazy-ffi)
173
174#~"libgtk-x11-2.0.so"
175#~"libglib-2.0.so"
176#~"libgobject-2.0.so"
177
178(define GTK_WINDOW_TOPLEVEL 0)
179
180(define-external (hello (c-pointer widget) (c-pointer data)) void
181  (print "Hello, world") )
182
183(define-external (delete_event (c-pointer widget)
184                               (c-pointer event)
185                               (c-pointer data) )
186  bool
187  (print "delete event occurred")
188  #t)
189
190(define-external (destroy (c-pointer widget) (c-pointer data)) void
191  (#~gtk_main_quit) )
192
193(define (g_signal_connect a b c d)
194  (#~g_signal_connect_data a b c pointer: d pointer: #f 0) )
195
196(#~gtk_init (foreign-value "&C_main_argc" c-pointer) (foreign-value "&C_main_argv" c-pointer))
197
198(define window (#~gtk_window_new GTK_WINDOW_TOPLEVEL return: pointer:))
199   
200(g_signal_connect window "delete_event" #$delete_event #f) 
201(g_signal_connect window "destroy" #$destroy #f)
202
203(#~gtk_container_set_border_width window 10)
204   
205(define button (#~gtk_button_new_with_label "Hello World" return: pointer:))
206   
207(g_signal_connect button "clicked" #$hello #f)
208
209(define-external (close_all (c-pointer widget)) void
210  (#~gtk_widget_destroy window) )
211
212(g_signal_connect button "clicked" #$close_all #f)
213(#~gtk_container_add window button)
214(#~gtk_widget_show button) 
215(#~gtk_widget_show window)
216(#~gtk_main safe: #t)
217</expr>
218</example></examples>
219
220Calling a pointer directly:
221
222<examples><example>
223<expr>
224#~"libdl.so.2"
225
226(define atof (#~dlsym pointer: #f "atof" return: pointer:)) ; lookup in current module
227
228(print atof)    ; ==> "#&lt;pointer 1077736272.0&gt;"
229
230(#~~ atof "99" return: double:)    ; ==> 99.0
231
232; Taking it to the extreme...
233
234(use lolevel)
235
236(#~~ (address->pointer 1077736272) "42.1" return: double:)    ; ==> 42.1
237</expr>
238</example></examples>
239
240=== Changelog
241
242* 1.8.2 Ported to chicken4
243* 1.8 Removed use of {{___callback}}
244* 1.7 Uses externalized easyffi extension, uses more modern CHICKEN features
245* 1.6 Fixed silly bug in f32vector handling
246* 1.5 Added basic argument and result handling for unsigned ints; allows {{#f}} as module name
247* 1.4 Changed read-syntax to {{#~}} and removed SRFI-4 type-specifiers (transformed automatically)
248* 1.3 Fixed bug (hash-table related, of course)
249* 1.2 Adapted to SRFI-69-compatible hash-tables
250* 1.1 Added {{~~}}
251* 1.0 Initial release
252
253=== License
254
255  Copyright (c) 2005, Felix L. Winkelmann
256  All rights reserved.
257 
258  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
259  conditions are met:
260 
261    Redistributions of source code must retain the above copyright notice, this list of conditions and the following
262      disclaimer.
263    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
264      disclaimer in the documentation and/or other materials provided with the distribution.
265    Neither the name of the author nor the names of its contributors may be used to endorse or promote
266      products derived from this software without specific prior written permission.
267 
268  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
269  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
270  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
271  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
272  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
273  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
274  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
275  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
276  POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.