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

Feature request: use C2Rust to generate Rust versions of static inline functions #1344

Open
fintelia opened this issue Jul 2, 2018 · 6 comments

Comments

@fintelia
Copy link

fintelia commented Jul 2, 2018

As described in #1090, bindgen is currently unable to expose static inline functions defined in C header files. This is because this functions do not actually exist anywhere in the linked library, but rather only in the header file itself. The proposed solution described in the other issue requires modifying the actual generated library on the C side which isn't always possible.

C2Rust is a new tool that can directly produce Rust code from C source, which would enable bindgen to actually produce Rust versions of these static inline functions. As a result, the Rust bindings would be able call these functions while still linking to unmodified versions of the original C library.

@emilio
Copy link
Contributor

emilio commented Jul 2, 2018

This would be really nice, though I think c2rust didn't support inline functions at least yet?

@fintelia
Copy link
Author

fintelia commented Jul 2, 2018

As best I can tell, it just ignores the "inline" keyword and generates the function as though it wasn't there, which isn't actually a problem for this use case. If we wanted to match the semantics exactly, it would simply be a matter of having #[inline] added above each generated function, which doesn't seem like that difficult of an addition

@thedataking
Copy link

We'd be happy to support this use case on the c2rust side. It might be worthwhile to discuss how bindgen and c2rust would interact. Since the c2rust transpiler is composed of two separate binaries (C++ frontend to serialize the clang AST + Rust backend to deserialize AST and emit Rust) it might be easiest to have bindgen call the transpiler as a subprocess if/when encountering a static inline function. On the return side, you'd end up with a whole translation unit by default but we could probably add an option to translate a single function and required data types if that simplifies things.

@emilio
Copy link
Contributor

emilio commented Jul 20, 2018

So, one of the pending things for bindgen I'd like to do but I never got around to is stopping to use libclang and use an actual c++ clang plugin for dealing with C++'s AST...

Dealing with libclang is cumbersome at times, specially for complex C++ (see #297).

I wonder if as part of this we should try to integrate c2rust's clang AST stuff into bindgen. That'd make fixing this a lot less awkward, we could just reuse the same C++ frontend, and then Bindgen would just call into c2rust for inline functions.

@chrysn
Copy link
Contributor

chrysn commented Sep 2, 2020

I've started some experimentation along these lines. As a first step, I'm not aiming for full integration into bindgen but rather for making C2Rust work in parallel, and when that works I'll think about how this can be integrated (which is nice eventually because it'll mean that the user doesn't need to know which module to grab the function from, and it could use the same Rust structs with both sides).

I won't update this on every single issue or step to keep the noise low, but will mention this in the C2Rust issues, so keep an eye open for them showing a mention here in the list as "mentioned this issue".

@chrysn
Copy link
Contributor

chrysn commented Sep 15, 2020

Working with C2Rust and bindgen in parallel, I notice more and more of overlap. In particular, with little tuning, In particular, C2Rust applied to headers generates, among other things, very similar output to bindgen.

With some extension to immunant/c2rust#291 (in particular, when preserving functions without a body), the differences I see are:

  • Only bindgen captures values defined in macros well (#define MY_VALUE 1234)
  • Only C2Rust expresses static inline functions
  • bindgen and C2Rust differ in the field names when they have a name in C that's unavailable in Rust (eg. type_0 vs type_). C2Rust considers moving towards raw identifiers at Use raw identifier for reserved keywords immunant/c2rust#295; also union fields named u8 (C2Rust uses u8_0). Names differ more for unnamed unions.
  • bindgen has good facilities for automatically implementing Debug where it can not be Derived
  • bindgen exposes documentation on functions.
  • bindgen and C2rust disagree on the necessity for alignment helpers on unions. For example, in a that both agree to come out as [u8; 16], [u8; 4] and u32 (that's a version-agnostic IP address), bindgen adds a _bindgen_union_align: [u32; 4] variant.
  • (There is some actual type disagreement, but I think that's only because I'm having legacy size_t_is_usize flag set.)

When using both in parallel (as is my current model to have C2Rust solve this issue's point), the main friction point is that the Rust types C2Rust and bindgen generate differ. This hits when calling functions (where arguments may need to be transmuted between compatible types), and manifests itself in "this signature doesn't match the previous declaration" warnings (hopefully not really that bad because it's from the aforementioned alignment helpers).

Right now, what I'm using is "mostly bindgen, with static inlines provided by C2Rust". I consider going the other way as "mostly C2Rust, with the constants and enum values provided by bindgen" -- especially if the small differences mentioned above were aligned, this should be a trivial switch. For the overall topic of using C2Rust to fill in the gaps in bindgen, this begs the question not of whether that's viable (it probably still is, provided some alignment), but whether it may make sense to consider whether the overlap may indicate an existing duplication of effort that might be worth addressing (and I have no clue yet as to which form that could take).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants