You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nomicon/ffi.md

46 lines
2.2 KiB

10 years ago
% Interfacing with other Languages (FFI)
*Obviously* we'd all love to live in a **glorious** world where everything is
written in Rust, Rust, and More Rust. Tragically, programs have been written
in Not Rust for over 50 years. Crufty enterprises are doomed to
support ancient code bases, and greybeard programmers stuck in their ways
*insist* on writing programs in other languages, even to this day!
In all seriousness, there's a myriad of reasons for your codebase to be a
hybrid of different languages, and Rust is well-designed to interface with
all of them as painlessly as possible. It does this through the tried and
true strategy of all languages: pretend to be C, and understand C.
Thanks to Rust's minimal runtime and C-like semantics, this is about as
painless as FFI with C++. Obviously, most of Rust's features are completely
incompatible with other languages: tagged unions, zero-sized-types, dynamically-
sized types, destructors, methods, traits, references, and lifetimes are all
concepts that you won't be able to expose or accept in your foreign function
interface.
All mapping through C will give you is functions, structs, globals, raw pointers,
and C-like enums. That's it. Rust's default data layouts are also incompatible
with the C layout. See [the section on data layout][data.html] for details.
Long story short: mark FFI structs and enums with `#[repr(C)]`, mark FFI
functions as `extern`.
## Runtime
Rust's runtime is sufficiently minimal that it requires *no* special handling.
You don't need to set anything up. You don't need to tear anything down.
Awesome.
The only runtime detail you *really* need to worry about is unwinding. Rust's
unwinding model is not defined to be incompatible with any particular language.
That means that if you call Rust from another language and it unwinds into the
calling language, this will cause Undefined Behaviour. Similarly, if another
language unwinds into Rust, it will also cause Undefined Behaviour.
Rust can't really do anything about other languages unwinding into it (FFI is unsafe
for a reason!), but you can be a good FFI citizen by catching panics in any
FFI functions you export. Rust provides `thread::catch_panic` for exactly this.
Unfortunately, this API is still unstable.
## libc