Rust and lack of header files

So I am learning rust and need to mix both C and RUST.

The steps I am trying to do are as follows:

STEP 1: I have a C structure - defined in the C language header file, this MUST remain in C for practical reasons, a representative structure is:

   // Structure defined in a C header file.
   struct  FOOBAR {
          int member1;
          int member2;
          // Real struct has probably 20 to 30 elements
    };

    int  rust_calls_this_function( struct foobar *pFOOBAR );

    int c_calls_this_rust_function( struct foobar *pFOOBAR );

Step 2 - I run "bindgen cli" to create this using a Makefile (using build.rs is not practical for this situation - mostly chicken and egg issues)

Effectively - this creates a "foobar.rs" file based on the C header file.

Step 3 - I also have C functions I need to call from RUST, so I need to use CBINDGEN to produce the Header file for the rust functions C will call.

Step 4 - This effectively means I have three copies or definitions of the "struct foobar" - COPY (1) in the original H file, Copy (2) in the generated foobar.rs file, and I guess I need yet another copy (3) in the rust code that calls the C functions.

This seems very wrong to me an I think I am doing something wrong.

Related: How does one provide the implementation of a RUST function in a sperate file? Example: "bindgen" produces a RS file from a C header, it effectively has function definitions akin to a C header file.

However - If I modify that generated RS file by adding the implementation for these functions they will be over written then next time they are re-generated.

So It would seem that I should put the IMPLIMENTATION in some separate file and sort of "include" the other generated file - but rust does not have the concept of an include file like C has. Thus I am confused.

So my question is: What is the best practice when faced with using a structure (and function signatures) that where/when the user requires bi-directional interaction with RUST and C.

I'm less familiar with the bindgen questions, but for "separate the implementation from the struct definition" in rust you can define an impl block anywhere the struct is visible. The visibility of the functions is still important, though (The pub in pub fn do_stuff is needed to call it from outside the defining module, separate from Foo's visibility)

so how would I do the following:

have the "generated_c_calls_rust.rs" file and say 5 different "implimentation_A.rs", "implimentation_B.rs" ... C, D and E files

HOW do I "include" the generated*.rs file(s) into the implementation files?

The bindgen docs recommend using the include! macro for this, as part of running bindgen whenever your crate is built. But for the differences between token-based macros and syntactic macros, the include! macro mostly does what you'd be familiar with if you're coming from a C background.

The other option, if the bindings will live in src, is to treat them as ordinary modules and add mod statements to lib.rs (or to a parent module) for them.

1 Like

You will need two definitions of the struct — one for C, and one for Rust.

bindgen is generally smart and correct, and you can use the struct it generated.

cbindgen is less sophisticated. If it doesn't generate output you like, then try tweaking its config (I think you can exclude types you don't want). If that doesn't help, you may need to patch its output in some post-processing step, or just manually.

You might just want a cbindgen.toml configuration line that tells it not to export that struct. (That is, don't translate it from Rust back to C again.)

I think it's something like

[export]
exclude = ["StructName"]

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.