"Alice Ryhl" <aliceryhl@xxxxxxxxxx> writes: > Rust has two different tools for generating function declarations to > call across the FFI boundary: > > * bindgen. Generates Rust declarations from a C header. > * cbindgen. Generates C headers from Rust declarations. > > In the kernel, we only use bindgen. This is because cbindgen assumes a > cargo-based buildsystem, so it is not compatible with the kernel's build > system. This means that when C code calls a Rust function by name, its > signature must be duplicated in both Rust code and a C header, and the > signature needs to be kept in sync manually. > > To eliminate this manual checking, introduce a new macro that verifies > at compile time that the two function declarations use the same > signature. The idea is to run the C declaration through bindgen, and > then have rustc verify that the function pointers have the same type. > > The signature must still be written twice, but at least you can no > longer get it wrong. If the signatures don't match, you will get errors > that look like this: > > error[E0308]: `if` and `else` have incompatible types > --> <linux>/rust/kernel/print.rs:22:22 > | > 21 | #[export] > | --------- expected because of this > 22 | unsafe extern "C" fn rust_fmt_argument( > | ^^^^^^^^^^^^^^^^^ expected `u8`, found `i8` > | > = note: expected fn item `unsafe extern "C" fn(*mut u8, *mut u8, *mut c_void) -> *mut u8 {bindings::rust_fmt_argument}` > found fn item `unsafe extern "C" fn(*mut i8, *mut i8, *const c_void) -> *mut i8 {print::rust_fmt_argument}` > > It is unfortunate that the error message starts out by saying "`if` and > `else` have incompatible types", but I believe the rest of the error > message is reasonably clear and not too confusing. > > Signed-off-by: Alice Ryhl <aliceryhl@xxxxxxxxxx> Reviewed-by: Andreas Hindborg <a.hindborg@xxxxxxxxxx> Best regards, Andreas Hindborg