Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust: automating helpers.c #352

Open
ojeda opened this issue Jun 4, 2021 · 1 comment
Open

rust: automating helpers.c #352

ojeda opened this issue Jun 4, 2021 · 1 comment
Labels
• toolchain Related to `rustc`, `bindgen`, `rustdoc`, LLVM, Clippy...

Comments

@ojeda
Copy link
Member

ojeda commented Jun 4, 2021

From @nbdd0121 #346 (comment):

It's a shame that bindgen can't handle static inline functions and c2rust can't handle macros :(

It would save us a lot hassle if we can just call into static inline functions.

and:

Idea: can we do some text processing, e.g. look into binding_generated.rs and generate a helper function only if it's missing in the generated binding?

E.g. add these only if errname is not showing up in binding_generated.rs:

helper_generated.c

const char *rust_helper_errname(int err)
{
	return errname(err);
}

binding_helper_generated.rs

extern "C" {
    #[link_name = "rust_helper_errname"]
    fn errname(err: c_types::c_int) -> *const c_types::c_char;
}
@ojeda ojeda added • toolchain Related to `rustc`, `bindgen`, `rustdoc`, LLVM, Clippy... prio: normal labels Jun 4, 2021
@nbdd0121
Copy link
Member

nbdd0121 commented Jun 4, 2021

Here's a way to get some automation:

  • Generate a header file full of rust_helper_foo definition for each foo generated by bindgen:
    sed -En 's/^.*pub fn ([a-zA-Z0-9_]*).*$/#define rust_helper_\1/pg' rust/bindings_generated.rs > some_header_file.h
  • Have #include "some_header_file.h" in helpers.c, and guard all helpers with #ifndef rust_helper_foo.
  • Use bindgen to generate the declarations:
    bindgen helpers.c --blocklist-type '.*' --allowlist-var '' --allowlist-function 'rust_helper_.*' (some other params) -o some_rust_file.rs
  • Fixup the binding names in that Rust file and add #[link_name]:
    sed -iE 's/pub fn rust_helper_([a-zA-Z0-9_]*)/\#[link_name="rust_helper_\1"]\n        pub fn \1/g' some_rust_file.rs
  • Include that rust file after bindings_generated.rs

Helpers functions still need to be written manually, but:

  • The user of the binding don't need to care about whether that's a helper function or an exported function anymore
  • The user of the binding don't need to write extern blocks themselves
  • The generated header file ensures that if there's an externed version of the symbol, it's picked up automatically and helper is not generated.
  • If C-side changes a function from inline to extern, no helper/Rust-side change is needed.
  • If C-side changes a function from extern to inline, a helper needs to be added, but there is no need to change any Rust code using the binding.

With some further macro tricks it's possible to just declare the type of the helpers and have the body generated by macros.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
• toolchain Related to `rustc`, `bindgen`, `rustdoc`, LLVM, Clippy...
Development

No branches or pull requests

2 participants