]>
Commit | Line | Data |
---|---|---|
85aaf69f | 1 | % Foreign Function Interface |
1a4d82fc JJ |
2 | |
3 | # Introduction | |
4 | ||
5 | This guide will use the [snappy](https://github.com/google/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://github.com/google/snappy/blob/master/snappy-c.h)). | |
10 | ||
11 | The following is a minimal example of calling a foreign function which will | |
12 | compile if snappy is installed: | |
13 | ||
85aaf69f | 14 | ```no_run |
c34b1796 | 15 | # #![feature(libc)] |
1a4d82fc JJ |
16 | extern crate libc; |
17 | use libc::size_t; | |
18 | ||
19 | #[link(name = "snappy")] | |
20 | extern { | |
21 | fn snappy_max_compressed_length(source_length: size_t) -> size_t; | |
22 | } | |
23 | ||
24 | fn main() { | |
25 | let x = unsafe { snappy_max_compressed_length(100) }; | |
26 | println!("max compressed length of a 100 byte buffer: {}", x); | |
27 | } | |
85aaf69f | 28 | ``` |
1a4d82fc JJ |
29 | |
30 | The `extern` block is a list of function signatures in a foreign library, in | |
31 | this case with the platform's C ABI. The `#[link(...)]` attribute is used to | |
32 | instruct the linker to link against the snappy library so the symbols are | |
33 | resolved. | |
34 | ||
35 | Foreign functions are assumed to be unsafe so calls to them need to be wrapped | |
36 | with `unsafe {}` as a promise to the compiler that everything contained within | |
37 | truly is safe. C libraries often expose interfaces that aren't thread-safe, and | |
38 | almost any function that takes a pointer argument isn't valid for all possible | |
39 | inputs since the pointer could be dangling, and raw pointers fall outside of | |
40 | Rust's safe memory model. | |
41 | ||
42 | When declaring the argument types to a foreign function, the Rust compiler can | |
43 | not check if the declaration is correct, so specifying it correctly is part of | |
44 | keeping the binding correct at runtime. | |
45 | ||
46 | The `extern` block can be extended to cover the entire snappy API: | |
47 | ||
85aaf69f | 48 | ```no_run |
c34b1796 | 49 | # #![feature(libc)] |
1a4d82fc JJ |
50 | extern crate libc; |
51 | use libc::{c_int, size_t}; | |
52 | ||
53 | #[link(name = "snappy")] | |
54 | extern { | |
55 | fn snappy_compress(input: *const u8, | |
56 | input_length: size_t, | |
57 | compressed: *mut u8, | |
58 | compressed_length: *mut size_t) -> c_int; | |
59 | fn snappy_uncompress(compressed: *const u8, | |
60 | compressed_length: size_t, | |
61 | uncompressed: *mut u8, | |
62 | uncompressed_length: *mut size_t) -> c_int; | |
63 | fn snappy_max_compressed_length(source_length: size_t) -> size_t; | |
64 | fn snappy_uncompressed_length(compressed: *const u8, | |
65 | compressed_length: size_t, | |
66 | result: *mut size_t) -> c_int; | |
67 | fn snappy_validate_compressed_buffer(compressed: *const u8, | |
68 | compressed_length: size_t) -> c_int; | |
69 | } | |
70 | # fn main() {} | |
85aaf69f | 71 | ``` |
1a4d82fc JJ |
72 | |
73 | # Creating a safe interface | |
74 | ||
75 | The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts | |
76 | like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe | |
77 | internal details. | |
78 | ||
79 | Wrapping the functions which expect buffers involves using the `slice::raw` module to manipulate Rust | |
80 | vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The | |
81 | length is number of elements currently contained, and the capacity is the total size in elements of | |
82 | the allocated memory. The length is less than or equal to the capacity. | |
83 | ||
62682a34 | 84 | ```rust |
c34b1796 | 85 | # #![feature(libc)] |
1a4d82fc JJ |
86 | # extern crate libc; |
87 | # use libc::{c_int, size_t}; | |
88 | # unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 } | |
89 | # fn main() {} | |
90 | pub fn validate_compressed_buffer(src: &[u8]) -> bool { | |
91 | unsafe { | |
92 | snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0 | |
93 | } | |
94 | } | |
85aaf69f | 95 | ``` |
1a4d82fc JJ |
96 | |
97 | The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the | |
98 | guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function | |
99 | signature. | |
100 | ||
101 | The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be | |
102 | allocated to hold the output too. | |
103 | ||
104 | The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum | |
105 | required capacity to hold the compressed output. The vector can then be passed to the | |
106 | `snappy_compress` function as an output parameter. An output parameter is also passed to retrieve | |
107 | the true length after compression for setting the length. | |
108 | ||
62682a34 | 109 | ```rust |
c34b1796 | 110 | # #![feature(libc)] |
1a4d82fc JJ |
111 | # extern crate libc; |
112 | # use libc::{size_t, c_int}; | |
113 | # unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8, | |
114 | # d: *mut size_t) -> c_int { 0 } | |
115 | # unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a } | |
116 | # fn main() {} | |
117 | pub fn compress(src: &[u8]) -> Vec<u8> { | |
118 | unsafe { | |
119 | let srclen = src.len() as size_t; | |
120 | let psrc = src.as_ptr(); | |
121 | ||
122 | let mut dstlen = snappy_max_compressed_length(srclen); | |
85aaf69f | 123 | let mut dst = Vec::with_capacity(dstlen as usize); |
1a4d82fc JJ |
124 | let pdst = dst.as_mut_ptr(); |
125 | ||
126 | snappy_compress(psrc, srclen, pdst, &mut dstlen); | |
85aaf69f | 127 | dst.set_len(dstlen as usize); |
1a4d82fc JJ |
128 | dst |
129 | } | |
130 | } | |
85aaf69f | 131 | ``` |
1a4d82fc JJ |
132 | |
133 | Decompression is similar, because snappy stores the uncompressed size as part of the compression | |
134 | format and `snappy_uncompressed_length` will retrieve the exact buffer size required. | |
135 | ||
62682a34 | 136 | ```rust |
c34b1796 | 137 | # #![feature(libc)] |
1a4d82fc JJ |
138 | # extern crate libc; |
139 | # use libc::{size_t, c_int}; | |
140 | # unsafe fn snappy_uncompress(compressed: *const u8, | |
141 | # compressed_length: size_t, | |
142 | # uncompressed: *mut u8, | |
143 | # uncompressed_length: *mut size_t) -> c_int { 0 } | |
144 | # unsafe fn snappy_uncompressed_length(compressed: *const u8, | |
145 | # compressed_length: size_t, | |
146 | # result: *mut size_t) -> c_int { 0 } | |
147 | # fn main() {} | |
148 | pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> { | |
149 | unsafe { | |
150 | let srclen = src.len() as size_t; | |
151 | let psrc = src.as_ptr(); | |
152 | ||
153 | let mut dstlen: size_t = 0; | |
154 | snappy_uncompressed_length(psrc, srclen, &mut dstlen); | |
155 | ||
85aaf69f | 156 | let mut dst = Vec::with_capacity(dstlen as usize); |
1a4d82fc JJ |
157 | let pdst = dst.as_mut_ptr(); |
158 | ||
159 | if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 { | |
85aaf69f | 160 | dst.set_len(dstlen as usize); |
1a4d82fc JJ |
161 | Some(dst) |
162 | } else { | |
163 | None // SNAPPY_INVALID_INPUT | |
164 | } | |
165 | } | |
166 | } | |
85aaf69f | 167 | ``` |
1a4d82fc | 168 | |
9346a6ac | 169 | For reference, the examples used here are also available as a [library on |
1a4d82fc JJ |
170 | GitHub](https://github.com/thestinger/rust-snappy). |
171 | ||
1a4d82fc JJ |
172 | # Destructors |
173 | ||
174 | Foreign libraries often hand off ownership of resources to the calling code. | |
175 | When this occurs, we must use Rust's destructors to provide safety and guarantee | |
176 | the release of these resources (especially in the case of panic). | |
177 | ||
c34b1796 AL |
178 | For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html). |
179 | ||
1a4d82fc JJ |
180 | # Callbacks from C code to Rust functions |
181 | ||
182 | Some external libraries require the usage of callbacks to report back their | |
183 | current state or intermediate data to the caller. | |
184 | It is possible to pass functions defined in Rust to an external library. | |
185 | The requirement for this is that the callback function is marked as `extern` | |
186 | with the correct calling convention to make it callable from C code. | |
187 | ||
188 | The callback function can then be sent through a registration call | |
189 | to the C library and afterwards be invoked from there. | |
190 | ||
191 | A basic example is: | |
192 | ||
193 | Rust code: | |
194 | ||
85aaf69f | 195 | ```no_run |
1a4d82fc JJ |
196 | extern fn callback(a: i32) { |
197 | println!("I'm called from C with value {0}", a); | |
198 | } | |
199 | ||
200 | #[link(name = "extlib")] | |
201 | extern { | |
202 | fn register_callback(cb: extern fn(i32)) -> i32; | |
203 | fn trigger_callback(); | |
204 | } | |
205 | ||
206 | fn main() { | |
207 | unsafe { | |
208 | register_callback(callback); | |
209 | trigger_callback(); // Triggers the callback | |
210 | } | |
211 | } | |
85aaf69f | 212 | ``` |
1a4d82fc JJ |
213 | |
214 | C code: | |
215 | ||
85aaf69f | 216 | ```c |
1a4d82fc JJ |
217 | typedef void (*rust_callback)(int32_t); |
218 | rust_callback cb; | |
219 | ||
220 | int32_t register_callback(rust_callback callback) { | |
221 | cb = callback; | |
222 | return 1; | |
223 | } | |
224 | ||
225 | void trigger_callback() { | |
226 | cb(7); // Will call callback(7) in Rust | |
227 | } | |
85aaf69f | 228 | ``` |
1a4d82fc JJ |
229 | |
230 | In this example Rust's `main()` will call `trigger_callback()` in C, | |
231 | which would, in turn, call back to `callback()` in Rust. | |
232 | ||
233 | ||
234 | ## Targeting callbacks to Rust objects | |
235 | ||
236 | The former example showed how a global function can be called from C code. | |
237 | However it is often desired that the callback is targeted to a special | |
238 | Rust object. This could be the object that represents the wrapper for the | |
239 | respective C object. | |
240 | ||
62682a34 | 241 | This can be achieved by passing an raw pointer to the object down to the |
1a4d82fc JJ |
242 | C library. The C library can then include the pointer to the Rust object in |
243 | the notification. This will allow the callback to unsafely access the | |
244 | referenced Rust object. | |
245 | ||
246 | Rust code: | |
247 | ||
85aaf69f | 248 | ```no_run |
1a4d82fc JJ |
249 | #[repr(C)] |
250 | struct RustObject { | |
251 | a: i32, | |
252 | // other members | |
253 | } | |
254 | ||
255 | extern "C" fn callback(target: *mut RustObject, a: i32) { | |
256 | println!("I'm called from C with value {0}", a); | |
257 | unsafe { | |
258 | // Update the value in RustObject with the value received from the callback | |
259 | (*target).a = a; | |
260 | } | |
261 | } | |
262 | ||
263 | #[link(name = "extlib")] | |
264 | extern { | |
265 | fn register_callback(target: *mut RustObject, | |
266 | cb: extern fn(*mut RustObject, i32)) -> i32; | |
267 | fn trigger_callback(); | |
268 | } | |
269 | ||
270 | fn main() { | |
271 | // Create the object that will be referenced in the callback | |
272 | let mut rust_object = Box::new(RustObject { a: 5 }); | |
273 | ||
274 | unsafe { | |
275 | register_callback(&mut *rust_object, callback); | |
276 | trigger_callback(); | |
277 | } | |
278 | } | |
85aaf69f | 279 | ``` |
1a4d82fc JJ |
280 | |
281 | C code: | |
282 | ||
85aaf69f | 283 | ```c |
1a4d82fc JJ |
284 | typedef void (*rust_callback)(void*, int32_t); |
285 | void* cb_target; | |
286 | rust_callback cb; | |
287 | ||
288 | int32_t register_callback(void* callback_target, rust_callback callback) { | |
289 | cb_target = callback_target; | |
290 | cb = callback; | |
291 | return 1; | |
292 | } | |
293 | ||
294 | void trigger_callback() { | |
295 | cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust | |
296 | } | |
85aaf69f | 297 | ``` |
1a4d82fc JJ |
298 | |
299 | ## Asynchronous callbacks | |
300 | ||
301 | In the previously given examples the callbacks are invoked as a direct reaction | |
302 | to a function call to the external C library. | |
303 | The control over the current thread is switched from Rust to C to Rust for the | |
304 | execution of the callback, but in the end the callback is executed on the | |
85aaf69f | 305 | same thread that called the function which triggered the callback. |
1a4d82fc JJ |
306 | |
307 | Things get more complicated when the external library spawns its own threads | |
308 | and invokes callbacks from there. | |
309 | In these cases access to Rust data structures inside the callbacks is | |
310 | especially unsafe and proper synchronization mechanisms must be used. | |
311 | Besides classical synchronization mechanisms like mutexes, one possibility in | |
c1a9b12d SL |
312 | Rust is to use channels (in `std::sync::mpsc`) to forward data from the C |
313 | thread that invoked the callback into a Rust thread. | |
1a4d82fc JJ |
314 | |
315 | If an asynchronous callback targets a special object in the Rust address space | |
316 | it is also absolutely necessary that no more callbacks are performed by the | |
317 | C library after the respective Rust object gets destroyed. | |
318 | This can be achieved by unregistering the callback in the object's | |
319 | destructor and designing the library in a way that guarantees that no | |
320 | callback will be performed after deregistration. | |
321 | ||
322 | # Linking | |
323 | ||
324 | The `link` attribute on `extern` blocks provides the basic building block for | |
325 | instructing rustc how it will link to native libraries. There are two accepted | |
326 | forms of the link attribute today: | |
327 | ||
328 | * `#[link(name = "foo")]` | |
329 | * `#[link(name = "foo", kind = "bar")]` | |
330 | ||
331 | In both of these cases, `foo` is the name of the native library that we're | |
332 | linking to, and in the second case `bar` is the type of native library that the | |
333 | compiler is linking to. There are currently three known types of native | |
334 | libraries: | |
335 | ||
336 | * Dynamic - `#[link(name = "readline")]` | |
337 | * Static - `#[link(name = "my_build_dependency", kind = "static")]` | |
338 | * Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]` | |
339 | ||
340 | Note that frameworks are only available on OSX targets. | |
341 | ||
342 | The different `kind` values are meant to differentiate how the native library | |
c1a9b12d | 343 | participates in linkage. From a linkage perspective, the Rust compiler creates |
1a4d82fc | 344 | two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary). |
62682a34 SL |
345 | Native dynamic library and framework dependencies are propagated to the final |
346 | artifact boundary, while static library dependencies are not propagated at | |
347 | all, because the static libraries are integrated directly into the subsequent | |
348 | artifact. | |
1a4d82fc JJ |
349 | |
350 | A few examples of how this model can be used are: | |
351 | ||
352 | * A native build dependency. Sometimes some C/C++ glue is needed when writing | |
c1a9b12d | 353 | some Rust code, but distribution of the C/C++ code in a library format is just |
1a4d82fc | 354 | a burden. In this case, the code will be archived into `libfoo.a` and then the |
c1a9b12d | 355 | Rust crate would declare a dependency via `#[link(name = "foo", kind = |
1a4d82fc JJ |
356 | "static")]`. |
357 | ||
358 | Regardless of the flavor of output for the crate, the native static library | |
359 | will be included in the output, meaning that distribution of the native static | |
360 | library is not necessary. | |
361 | ||
362 | * A normal dynamic dependency. Common system libraries (like `readline`) are | |
363 | available on a large number of systems, and often a static copy of these | |
c1a9b12d | 364 | libraries cannot be found. When this dependency is included in a Rust crate, |
1a4d82fc JJ |
365 | partial targets (like rlibs) will not link to the library, but when the rlib |
366 | is included in a final target (like a binary), the native library will be | |
367 | linked in. | |
368 | ||
369 | On OSX, frameworks behave with the same semantics as a dynamic library. | |
370 | ||
1a4d82fc JJ |
371 | # Unsafe blocks |
372 | ||
62682a34 | 373 | Some operations, like dereferencing raw pointers or calling functions that have been marked |
1a4d82fc JJ |
374 | unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to |
375 | the compiler that the unsafety does not leak out of the block. | |
376 | ||
377 | Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like | |
378 | this: | |
379 | ||
62682a34 | 380 | ```rust |
c34b1796 | 381 | unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr } |
85aaf69f | 382 | ``` |
1a4d82fc JJ |
383 | |
384 | This function can only be called from an `unsafe` block or another `unsafe` function. | |
385 | ||
386 | # Accessing foreign globals | |
387 | ||
388 | Foreign APIs often export a global variable which could do something like track | |
389 | global state. In order to access these variables, you declare them in `extern` | |
390 | blocks with the `static` keyword: | |
391 | ||
85aaf69f | 392 | ```no_run |
c34b1796 | 393 | # #![feature(libc)] |
1a4d82fc JJ |
394 | extern crate libc; |
395 | ||
396 | #[link(name = "readline")] | |
397 | extern { | |
398 | static rl_readline_version: libc::c_int; | |
399 | } | |
400 | ||
401 | fn main() { | |
402 | println!("You have readline version {} installed.", | |
c34b1796 | 403 | rl_readline_version as i32); |
1a4d82fc | 404 | } |
85aaf69f | 405 | ``` |
1a4d82fc JJ |
406 | |
407 | Alternatively, you may need to alter global state provided by a foreign | |
85aaf69f | 408 | interface. To do this, statics can be declared with `mut` so we can mutate |
1a4d82fc JJ |
409 | them. |
410 | ||
85aaf69f | 411 | ```no_run |
c34b1796 | 412 | # #![feature(libc)] |
1a4d82fc JJ |
413 | extern crate libc; |
414 | ||
415 | use std::ffi::CString; | |
416 | use std::ptr; | |
417 | ||
418 | #[link(name = "readline")] | |
419 | extern { | |
420 | static mut rl_prompt: *const libc::c_char; | |
421 | } | |
422 | ||
423 | fn main() { | |
85aaf69f SL |
424 | let prompt = CString::new("[my-awesome-shell] $").unwrap(); |
425 | unsafe { | |
426 | rl_prompt = prompt.as_ptr(); | |
427 | ||
428 | println!("{:?}", rl_prompt); | |
429 | ||
430 | rl_prompt = ptr::null(); | |
431 | } | |
1a4d82fc | 432 | } |
85aaf69f SL |
433 | ``` |
434 | ||
435 | Note that all interaction with a `static mut` is unsafe, both reading and | |
436 | writing. Dealing with global mutable state requires a great deal of care. | |
1a4d82fc JJ |
437 | |
438 | # Foreign calling conventions | |
439 | ||
440 | Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when | |
441 | calling foreign functions. Some foreign functions, most notably the Windows API, use other calling | |
442 | conventions. Rust provides a way to tell the compiler which convention to use: | |
443 | ||
62682a34 | 444 | ```rust |
c34b1796 | 445 | # #![feature(libc)] |
1a4d82fc JJ |
446 | extern crate libc; |
447 | ||
448 | #[cfg(all(target_os = "win32", target_arch = "x86"))] | |
449 | #[link(name = "kernel32")] | |
450 | #[allow(non_snake_case)] | |
451 | extern "stdcall" { | |
452 | fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int; | |
453 | } | |
454 | # fn main() { } | |
85aaf69f | 455 | ``` |
1a4d82fc JJ |
456 | |
457 | This applies to the entire `extern` block. The list of supported ABI constraints | |
458 | are: | |
459 | ||
460 | * `stdcall` | |
461 | * `aapcs` | |
462 | * `cdecl` | |
463 | * `fastcall` | |
464 | * `Rust` | |
465 | * `rust-intrinsic` | |
466 | * `system` | |
467 | * `C` | |
468 | * `win64` | |
469 | ||
470 | Most of the abis in this list are self-explanatory, but the `system` abi may | |
471 | seem a little odd. This constraint selects whatever the appropriate ABI is for | |
472 | interoperating with the target's libraries. For example, on win32 with a x86 | |
473 | architecture, this means that the abi used would be `stdcall`. On x86_64, | |
474 | however, windows uses the `C` calling convention, so `C` would be used. This | |
475 | means that in our previous example, we could have used `extern "system" { ... }` | |
476 | to define a block for all windows systems, not just x86 ones. | |
477 | ||
478 | # Interoperability with foreign code | |
479 | ||
480 | Rust guarantees that the layout of a `struct` is compatible with the platform's | |
481 | representation in C only if the `#[repr(C)]` attribute is applied to it. | |
482 | `#[repr(C, packed)]` can be used to lay out struct members without padding. | |
483 | `#[repr(C)]` can also be applied to an enum. | |
484 | ||
485 | Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point | |
486 | to the contained object. However, they should not be manually created because | |
487 | they are managed by internal allocators. References can safely be assumed to be | |
488 | non-nullable pointers directly to the type. However, breaking the borrow | |
489 | checking or mutability rules is not guaranteed to be safe, so prefer using raw | |
490 | pointers (`*`) if that's needed because the compiler can't make as many | |
491 | assumptions about them. | |
492 | ||
493 | Vectors and strings share the same basic memory layout, and utilities are | |
494 | available in the `vec` and `str` modules for working with C APIs. However, | |
495 | strings are not terminated with `\0`. If you need a NUL-terminated string for | |
496 | interoperability with C, you should use the `CString` type in the `std::ffi` | |
497 | module. | |
498 | ||
e9174d1e SL |
499 | The [`libc` crate on crates.io][libc] includes type aliases and function |
500 | definitions for the C standard library in the `libc` module, and Rust links | |
501 | against `libc` and `libm` by default. | |
502 | ||
503 | [libc]: https://crates.io/crates/libc | |
1a4d82fc JJ |
504 | |
505 | # The "nullable pointer optimization" | |
506 | ||
507 | Certain types are defined to not be `null`. This includes references (`&T`, | |
508 | `&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). | |
509 | When interfacing with C, pointers that might be null are often used. | |
510 | As a special case, a generic `enum` that contains exactly two variants, one of | |
511 | which contains no data and the other containing a single field, is eligible | |
512 | for the "nullable pointer optimization". When such an enum is instantiated | |
513 | with one of the non-nullable types, it is represented as a single pointer, | |
514 | and the non-data variant is represented as the null pointer. So | |
515 | `Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable | |
516 | function pointer using the C ABI. | |
85aaf69f SL |
517 | |
518 | # Calling Rust code from C | |
519 | ||
520 | You may wish to compile Rust code in a way so that it can be called from C. This is | |
521 | fairly easy, but requires a few things: | |
522 | ||
62682a34 | 523 | ```rust |
85aaf69f SL |
524 | #[no_mangle] |
525 | pub extern fn hello_rust() -> *const u8 { | |
526 | "Hello, world!\0".as_ptr() | |
527 | } | |
528 | # fn main() {} | |
529 | ``` | |
530 | ||
531 | The `extern` makes this function adhere to the C calling convention, as | |
532 | discussed above in "[Foreign Calling | |
533 | Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` | |
534 | attribute turns off Rust's name mangling, so that it is easier to link to. | |
62682a34 SL |
535 | |
536 | # FFI and panics | |
537 | ||
c1a9b12d SL |
538 | It’s important to be mindful of `panic!`s when working with FFI. A `panic!` |
539 | across an FFI boundary is undefined behavior. If you’re writing code that may | |
540 | panic, you should run it in another thread, so that the panic doesn’t bubble up | |
541 | to C: | |
62682a34 SL |
542 | |
543 | ```rust | |
544 | use std::thread; | |
545 | ||
546 | #[no_mangle] | |
547 | pub extern fn oh_no() -> i32 { | |
548 | let h = thread::spawn(|| { | |
549 | panic!("Oops!"); | |
550 | }); | |
551 | ||
552 | match h.join() { | |
553 | Ok(_) => 1, | |
554 | Err(_) => 0, | |
555 | } | |
556 | } | |
557 | # fn main() {} | |
558 | ``` | |
559 | ||
e9174d1e SL |
560 | # Representing opaque structs |
561 | ||
562 | Sometimes, a C library wants to provide a pointer to something, but not let you | |
563 | know the internal details of the thing it wants. The simplest way is to use a | |
564 | `void *` argument: | |
565 | ||
566 | ```c | |
567 | void foo(void *arg); | |
568 | void bar(void *arg); | |
569 | ``` | |
570 | ||
571 | We can represent this in Rust with the `c_void` type: | |
572 | ||
573 | ```rust | |
574 | # #![feature(libc)] | |
575 | extern crate libc; | |
576 | ||
577 | extern "C" { | |
578 | pub fn foo(arg: *mut libc::c_void); | |
579 | pub fn bar(arg: *mut libc::c_void); | |
580 | } | |
581 | # fn main() {} | |
582 | ``` | |
583 | ||
584 | This is a perfectly valid way of handling the situation. However, we can do a bit | |
585 | better. To solve this, some C libraries will instead create a `struct`, where | |
586 | the details and memory layout of the struct are private. This gives some amount | |
587 | of type safety. These structures are called ‘opaque’. Here’s an example, in C: | |
588 | ||
589 | ```c | |
590 | struct Foo; /* Foo is a structure, but its contents are not part of the public interface */ | |
591 | struct Bar; | |
592 | void foo(struct Foo *arg); | |
593 | void bar(struct Bar *arg); | |
594 | ``` | |
595 | ||
596 | To do this in Rust, let’s create our own opaque types with `enum`: | |
597 | ||
598 | ```rust | |
599 | pub enum Foo {} | |
600 | pub enum Bar {} | |
601 | ||
602 | extern "C" { | |
603 | pub fn foo(arg: *mut Foo); | |
604 | pub fn bar(arg: *mut Bar); | |
605 | } | |
606 | # fn main() {} | |
607 | ``` | |
608 | ||
609 | By using an `enum` with no variants, we create an opaque type that we can’t | |
610 | instantiate, as it has no variants. But because our `Foo` and `Bar` types are | |
611 | different, we’ll get type safety between the two of them, so we cannot | |
612 | accidentally pass a pointer to `Foo` to `bar()`. |