From 08dccd05a79d2cf2bdd4b6cd8ccaa8baa02b0a54 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 27 Aug 2021 08:43:12 +0200 Subject: [PATCH] Initial libmount function call from Rust Follow "A little C with your Rust" [1]. Set up cargo and main.rs skeleton and call one of the simplest possible functions from libmount: mnt_get_fstab_path(). Use bindgen [1] to translate libmount's header file into a Rust interface. This requires a few hacks: - bindgen does not accept the original header right away, as it can't find stdarg.h. Avoid this by dropping the (unnecessary) stdio.h include. - bindgen does not know about `size_t`. Hack around that with a typedef for now. - Suppress warnings about constant/identifier naming. [1] https://rust-lang.github.io/rust-bindgen/command-line-usage.html [2] https://docs.rust-embedded.org/book/interoperability/c-with-rust.html --- .gitignore | 1 + call-c-from-rust/.cargo/config | 2 ++ call-c-from-rust/Cargo.toml | 8 ++++++++ call-c-from-rust/Makefile | 16 ++++++++++++++-- call-c-from-rust/src/main.rs | 10 ++++++++++ 5 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 call-c-from-rust/.cargo/config create mode 100644 call-c-from-rust/Cargo.toml create mode 100644 call-c-from-rust/src/main.rs diff --git a/.gitignore b/.gitignore index 5c03031..7ecae2e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ Cargo.lock target +libmount.rs c-langinfo c-mounts diff --git a/call-c-from-rust/.cargo/config b/call-c-from-rust/.cargo/config new file mode 100644 index 0000000..53fb2de --- /dev/null +++ b/call-c-from-rust/.cargo/config @@ -0,0 +1,2 @@ +[build] +rustflags = "-C link-args=-lmount" diff --git a/call-c-from-rust/Cargo.toml b/call-c-from-rust/Cargo.toml new file mode 100644 index 0000000..535c6b9 --- /dev/null +++ b/call-c-from-rust/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "learning-c-from-rust" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/call-c-from-rust/Makefile b/call-c-from-rust/Makefile index 583e2f2..cbeefdd 100644 --- a/call-c-from-rust/Makefile +++ b/call-c-from-rust/Makefile @@ -1,7 +1,7 @@ CFLAGS += $(shell pkg-config --cflags mount) LIBMOUNT = $(shell pkg-config --libs mount) -all: c-mounts c-langinfo +all: c-mounts c-langinfo target/debug/learning-c-from-rust c-mounts: c-mounts.o $(CC) -Wall -o $@ $^ $(LIBMOUNT) @@ -9,13 +9,25 @@ c-mounts: c-mounts.o c-langinfo: c-langinfo.o $(CC) -Wall -o $@ $^ +# HACK: does not find stdarg.h (through stdio.h), missing size_t +# also avoid hundreds of "should have an upper camel case name" warnings +src/libmount.rs: + sed 's/#include.*stdio.h.*/typedef unsigned long size_t;/' /usr/include/libmount/libmount.h > libmount-hack.h + bindgen libmount-hack.h -- -I/usr/include/linux/ > $@.tmp + (echo '#![allow(non_camel_case_types,non_upper_case_globals,dead_code)]'; cat $@.tmp) > $@ + rm libmount-hack.h $@.tmp + +target/debug/learning-c-from-rust: src/libmount.rs src/main.rs + cargo build + clean: - rm -f c-mounts c-langinfo *.o + rm -f c-mounts c-langinfo *.o src/libmount.rs run: all LANG=en_US.UTF-8 ./c-langinfo LANG=en_GB.UTF-8 ./c-langinfo LANG=en_IE.UTF-8 ./c-langinfo ./c-mounts + target/debug/learning-c-from-rust .PHONY: clean run diff --git a/call-c-from-rust/src/main.rs b/call-c-from-rust/src/main.rs new file mode 100644 index 0000000..b453d81 --- /dev/null +++ b/call-c-from-rust/src/main.rs @@ -0,0 +1,10 @@ +mod libmount; + +use std::ffi::CStr; + +fn main() { + let fstab_path_cstr: &CStr = unsafe { CStr::from_ptr (libmount::mnt_get_fstab_path()) }; + println!("fstab path C-String: {:?}", fstab_path_cstr); + let fstab_path = fstab_path_cstr.to_str().unwrap(); // may cause UTF-8 decoding error + println!("fstab path str: {}", fstab_path); +} -- 2.39.5