After cross-compiling with the NDK, I was overwhelmed by several library files in Rust, which needed to port libjpeg-Turbo to Rust for a company project. There are so few rust-related articles in China that I have to turn to Github and Stack Overflow for answers. This article is a summary of the Rust FFI chapter.
FFI
Ffi refers to the foreign Function Interface and rust calls C/C ++ and C/C ++ calls rust. All kinds of books and all kinds of teaching articles have already spelled out how they're going to do it, so we won't bother here. Rustc command (rustc -l /path/to/lib XXX.rs). There are very, very few cargo configurations involved.Copy the code
Related links: doc.rust-lang.org/cargo/refer…
The Outputs of the Build Script section of the Cargo Book tells us how to configure build.rs for some purpose. After some last attempts, I found out how to configure linking to our custom C/C ++ library files in cargo managed projects
practice
Start by preparing the library file we need to link to
$ touch test.c
Copy the code
The following
#include<stdio.h> void say_hello() { printf("Hello Rust! \n"); }Copy the code
It’s a very simple function, and we’re going to compile it into a static library of.A
$ cc -c test.c -o test.o
$ ar -r libtest.a test.o
Copy the code
Next we create a new Rust project using Cargo
$ cargo new link_test --bin
Copy the code
Here is an IDE for you. I am currently using the AndroidStudio + Rust plugin. InterliJ IDEA + Rust should also be good, never tried. But AndroidStudio is built on top of it.
Edited by Cargo. Toml below
[package] name = "link_test" version = "0.1.0" authors = ["authors"] edition = "2018" build = "SRC /build.rs" [build - dependencies] dunce = "while"Copy the code
Create build.rs in the SRC directory (you can also configure it in Cargo. Toml in other directories)
high energy alert
The contents of build.rs are as follows:
extern crate dunce; use std::{env, path::PathBuf}; fn main() { let library_name = "test"; let root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); let library_dir = dunce::canonicalize(root.join("src")).unwrap(); println! ("cargo:rustc-link-lib=static={}", library_name); println! ("cargo:rustc-link-search=native={}", env::join_paths(&[library_dir]).unwrap().to_str().unwrap()); }Copy the code
Mainly these two sentences:
println! ("cargo:rustc-link-lib=static={}", library_name); println! ("cargo:rustc-link-search=native={}",env::join_paths(&[library_dir]).unwrap().to_str().unwrap());Copy the code
Cargo is told to configure the type and name of the ruSTC library file. The type is static because we are using the static library. There are also dylib and framework options, but I haven’t been able to connect dylib to the dynamic library You can see more with the –help command). The second sentence tells Cargo to configure the directory where the RUSTC library files are located
To see if our configuration works, drop the library files into the SRC directory. The directory structure is as follows:
|____Cargo.lock
|____Cargo.toml
|____src
| |____build.rs
| |____main.rs
| |____libtest.a
Copy the code
Open our main.rs and add the following code:
fn main() {
unsafe { say_hello(); }
}
#[link(name = "test", kind = "static")]
extern "C" {
pub fn say_hello();
}
Copy the code
The last
$ cargo run
$ Hello Rust!
Copy the code
As you can see, the function defined in C has already been executed!