]> git.lizzy.rs Git - rust.git/blob - doc/tutorial-ffi.md
auto merge of #8350 : dim-an/rust/fix-struct-match, r=pcwalton
[rust.git] / doc / tutorial-ffi.md
1 % Rust Foreign Function Interface Tutorial
2
3 # Introduction
4
5 This tutorial will use the [snappy](https://code.google.com/p/snappy/)
6 compression/decompression library as an introduction to writing bindings for
7 foreign code. Rust is currently unable to call directly into a C++ library, but
8 snappy includes a C interface (documented in
9 [`snappy-c.h`](https://code.google.com/p/snappy/source/browse/trunk/snappy-c.h)).
10
11 The following is a minimal example of calling a foreign function which will compile if snappy is
12 installed:
13
14 ~~~~ {.xfail-test}
15 use std::libc::size_t;
16
17 #[link_args = "-lsnappy"]
18 extern {
19     fn snappy_max_compressed_length(source_length: size_t) -> size_t;
20 }
21
22 fn main() {
23     let x = unsafe { snappy_max_compressed_length(100) };
24     println(fmt!("max compressed length of a 100 byte buffer: %?", x));
25 }
26 ~~~~
27
28 The `extern` block is a list of function signatures in a foreign library, in this case with the
29 platform's C ABI. The `#[link_args]` attribute is used to instruct the linker to link against the
30 snappy library so the symbols are resolved.
31
32 Foreign functions are assumed to be unsafe so calls to them need to be wrapped with `unsafe {}` as a
33 promise to the compiler that everything contained within truly is safe. C libraries often expose
34 interfaces that aren't thread-safe, and almost any function that takes a pointer argument isn't
35 valid for all possible inputs since the pointer could be dangling, and raw pointers fall outside of
36 Rust's safe memory model.
37
38 When declaring the argument types to a foreign function, the Rust compiler will not check if the
39 declaration is correct, so specifying it correctly is part of keeping the binding correct at
40 runtime.
41
42 The `extern` block can be extended to cover the entire snappy API:
43
44 ~~~~ {.xfail-test}
45 use std::libc::{c_int, size_t};
46
47 #[link_args = "-lsnappy"]
48 extern {
49     fn snappy_compress(input: *u8,
50                        input_length: size_t,
51                        compressed: *mut u8,
52                        compressed_length: *mut size_t) -> c_int;
53     fn snappy_uncompress(compressed: *u8,
54                          compressed_length: size_t,
55                          uncompressed: *mut u8,
56                          uncompressed_length: *mut size_t) -> c_int;
57     fn snappy_max_compressed_length(source_length: size_t) -> size_t;
58     fn snappy_uncompressed_length(compressed: *u8,
59                                   compressed_length: size_t,
60                                   result: *mut size_t) -> c_int;
61     fn snappy_validate_compressed_buffer(compressed: *u8,
62                                          compressed_length: size_t) -> c_int;
63 }
64 ~~~~
65
66 # Creating a safe interface
67
68 The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts
69 like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe
70 internal details.
71
72 Wrapping the functions which expect buffers involves using the `vec::raw` module to manipulate Rust
73 vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The
74 length is number of elements currently contained, and the capacity is the total size in elements of
75 the allocated memory. The length is less than or equal to the capacity.
76
77 ~~~~ {.xfail-test}
78 pub fn validate_compressed_buffer(src: &[u8]) -> bool {
79     unsafe {
80         snappy_validate_compressed_buffer(vec::raw::to_ptr(src), src.len() as size_t) == 0
81     }
82 }
83 ~~~~
84
85 The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the
86 guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
87 signature.
88
89 The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be
90 allocated to hold the output too.
91
92 The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum
93 required capacity to hold the compressed output. The vector can then be passed to the
94 `snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
95 the true length after compression for setting the length.
96
97 ~~~~ {.xfail-test}
98 pub fn compress(src: &[u8]) -> ~[u8] {
99     unsafe {
100         let srclen = src.len() as size_t;
101         let psrc = vec::raw::to_ptr(src);
102
103         let mut dstlen = snappy_max_compressed_length(srclen);
104         let mut dst = vec::with_capacity(dstlen as uint);
105         let pdst = vec::raw::to_mut_ptr(dst);
106
107         snappy_compress(psrc, srclen, pdst, &mut dstlen);
108         vec::raw::set_len(&mut dst, dstlen as uint);
109         dst
110     }
111 }
112 ~~~~
113
114 Decompression is similar, because snappy stores the uncompressed size as part of the compression
115 format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
116
117 ~~~~ {.xfail-test}
118 pub fn uncompress(src: &[u8]) -> Option<~[u8]> {
119     unsafe {
120         let srclen = src.len() as size_t;
121         let psrc = vec::raw::to_ptr(src);
122
123         let mut dstlen: size_t = 0;
124         snappy_uncompressed_length(psrc, srclen, &mut dstlen);
125
126         let mut dst = vec::with_capacity(dstlen as uint);
127         let pdst = vec::raw::to_mut_ptr(dst);
128
129         if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
130             vec::raw::set_len(&mut dst, dstlen as uint);
131             Some(dst)
132         } else {
133             None // SNAPPY_INVALID_INPUT
134         }
135     }
136 }
137 ~~~~
138
139 For reference, the examples used here are also available as an [library on
140 GitHub](https://github.com/thestinger/rust-snappy).
141
142 # Destructors
143
144 Foreign libraries often hand off ownership of resources to the calling code,
145 which should be wrapped in a destructor to provide safety and guarantee their
146 release.
147
148 A type with the same functionality as owned boxes can be implemented by
149 wrapping `malloc` and `free`:
150
151 ~~~~
152 use std::cast;
153 use std::libc::{c_void, size_t, malloc, free};
154 use std::ptr;
155 use std::unstable::intrinsics;
156
157 // a wrapper around the handle returned by the foreign code
158 pub struct Unique<T> {
159     priv ptr: *mut T
160 }
161
162 impl<T: Send> Unique<T> {
163     pub fn new(value: T) -> Unique<T> {
164         unsafe {
165             let ptr = malloc(std::sys::size_of::<T>() as size_t) as *mut T;
166             assert!(!ptr::is_null(ptr));
167             // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
168             intrinsics::move_val_init(&mut *ptr, value);
169             Unique{ptr: ptr}
170         }
171     }
172
173     // the 'r lifetime results in the same semantics as `&*x` with ~T
174     pub fn borrow<'r>(&'r self) -> &'r T {
175         unsafe { cast::copy_lifetime(self, &*self.ptr) }
176     }
177
178     // the 'r lifetime results in the same semantics as `&mut *x` with ~T
179     pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {
180         unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) }
181     }
182 }
183
184 #[unsafe_destructor]
185 impl<T: Send> Drop for Unique<T> {
186     fn drop(&self) {
187         unsafe {
188             let x = intrinsics::init(); // dummy value to swap in
189             // moving the object out is needed to call the destructor
190             ptr::replace_ptr(self.ptr, x);
191             free(self.ptr as *c_void)
192         }
193     }
194 }
195
196 // A comparison between the built-in ~ and this reimplementation
197 fn main() {
198     {
199         let mut x = ~5;
200         *x = 10;
201     } // `x` is freed here
202
203     {
204         let mut y = Unique::new(5);
205         *y.borrow_mut() = 10;
206     } // `y` is freed here
207 }
208 ~~~~
209
210 # Linking
211
212 In addition to the `#[link_args]` attribute for explicitly passing arguments to the linker, an
213 `extern mod` block will pass `-lmodname` to the linker by default unless it has a `#[nolink]`
214 attribute applied.
215
216 # Unsafe blocks
217
218 Some operations, like dereferencing unsafe pointers or calling functions that have been marked
219 unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to
220 the compiler that the unsafety does not leak out of the block.
221
222 Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
223 this:
224
225 ~~~~
226 unsafe fn kaboom(ptr: *int) -> int { *ptr }
227 ~~~~
228
229 This function can only be called from an `unsafe` block or another `unsafe` function.
230
231 # Accessing foreign globals
232
233 Foreign APIs often export a global variable which could do something like track
234 global state. In order to access these variables, you declare them in `extern`
235 blocks with the `static` keyword:
236
237 ~~~{.xfail-test}
238 use std::libc;
239
240 #[link_args = "-lreadline"]
241 extern {
242     static rl_readline_version: libc::c_int;
243 }
244
245 fn main() {
246     println(fmt!("You have readline version %d installed.",
247                  rl_readline_version as int));
248 }
249 ~~~
250
251 Alternatively, you may need to alter global state provided by a foreign
252 interface. To do this, statics can be declared with `mut` so rust can mutate
253 them.
254
255 ~~~{.xfail-test}
256 use std::libc;
257 use std::ptr;
258
259 #[link_args = "-lreadline"]
260 extern {
261     static mut rl_prompt: *libc::c_char;
262 }
263
264 fn main() {
265     do "[my-awesome-shell] $".as_c_str |buf| {
266         unsafe { rl_prompt = buf; }
267         // get a line, process it
268         unsafe { rl_prompt = ptr::null(); }
269     }
270 }
271 ~~~
272
273 # Foreign calling conventions
274
275 Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when
276 calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
277 conventions. Rust provides the `abi` attribute as a way to hint to the compiler which calling
278 convention to use:
279
280 ~~~~
281 #[cfg(target_os = "win32")]
282 #[abi = "stdcall"]
283 #[link_name = "kernel32"]
284 extern {
285     fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;
286 }
287 ~~~~
288
289 The `abi` attribute applies to a foreign module (it cannot be applied to a single function within a
290 module), and must be either `"cdecl"` or `"stdcall"`. The compiler may eventually support other
291 calling conventions.
292
293 # Interoperability with foreign code
294
295 Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C.
296 A `#[packed]` attribute is available, which will lay out the struct members without padding.
297 However, there are currently no guarantees about the layout of an `enum`.
298
299 Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained
300 object. However, they should not be manually created because they are managed by internal
301 allocators. Borrowed pointers can safely be assumed to be non-nullable pointers directly to the
302 type. However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so
303 prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions
304 about them.
305
306 Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
307 `str` modules for working with C APIs. Strings are terminated with `\0` for interoperability with C,
308 but it should not be assumed because a slice will not always be nul-terminated. Instead, the
309 `str::as_c_str` function should be used.
310
311 The standard library includes type aliases and function definitions for the C standard library in
312 the `libc` module, and Rust links against `libc` and `libm` by default.