Write a basic "call Rust from C" example

pull/296/head
Yuki Okushi 3 years ago
parent fe6227eb3c
commit 64553aa569
No known key found for this signature in database
GPG Key ID: DABA5B072961C18A

@ -650,21 +650,68 @@ No `transmute` required!
## Calling Rust code from C
You may wish to compile Rust code in a way so that it can be called from C. This is
fairly easy, but requires a few things:
You may wish to compile Rust code in a way so that it can be called from C.
This is fairly easy, but requires a few things.
### Rust side
First, we assume you have a lib crate named as `rust_from_c`.
`lib.rs` should have Rust code as following:
```rust
#[no_mangle]
pub extern "C" fn hello_rust() -> *const u8 {
"Hello, world!\0".as_ptr()
pub extern "C" fn hello_from_rust() {
println!("Hello from Rust!");
}
# fn main() {}
```
The `extern "C"` makes this function adhere to the C calling convention, as
discussed above in "[Foreign Calling
Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle`
attribute turns off Rust's name mangling, so that it is easier to link to.
The `extern "C"` makes this function adhere to the C calling convention, as discussed above in "[Foreign Calling Conventions]".
The `no_mangle` attribute turns off Rust's name mangling, so that it is easier to link to.
Then, to compile Rust code as a shared library that can be called from C, add the following to your `Cargo.toml`:
```toml
[lib]
crate-type = ["cdylib"]
```
Run `cargo build` and you're ready to go on the Rust side.
[Foreign Calling Conventions]: ffi.html#foreign-calling-conventions
### C side
We'll create a C file to call the `hello_from_rust` function and compile it by `gcc`.
C file should look like:
```c
int main() {
hello_from_rust();
return 0;
}
```
We name the file as `call_rust.c` and place it on the crate root.
Run the following to compile:
```sh
gcc call_rust.c -o call_rust -lrust_from_c -L./target/debug
```
`-l` and `-L` tell gcc to find our Rust library.
Finally, we can call Rust code from C with `LD_LIBRARY_PATH` specified:
```sh
LD_LIBRARY_PATH=./target/debug ./call_rust
```
That's it!
For more realistic example, check the [`cbindgen`].
[`cbindgen`]: https://github.com/eqrion/cbindgen
## FFI and panics

Loading…
Cancel
Save