rust-lang / rust-lang/rust-bindgen

Definitions of static or macro-defined arrays are not emitted

Open
#1,266 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-libclang enhancement
Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

Input C Header
#define MACRO_ARRAY {1, 2}

static const int static_const_array[] = {3, 4};
Bindgen Invocation
$ bindgen input.h
Actual Results
extern "C" {
    #[link_name = "\u{1}static_const_array"]
    pub static mut static_const_array: [::std::os::raw::c_int; 2usize];
}

(The presence of the mut is #511, it's not the point of this issue but I'm just noting that that's a separate incorrect thing here.)

Expected Results

As it is, neither array can be used with bindgen alone. MACRO_ARRAY is not emitted and attempting to use static_const_array will result in a link error, because there is no definition, only a declaration.

I was hoping to see at least:

static static_const_array: [::std::os::raw::c_int; 2usize] = [3, 4];

And ideally:

// Inferred as c_int based on the types of 1 and 2
static MACRO_ARRAY: [::std::os::raw::c_int; 2usize] = [1, 2];

static static_const_array: [::std::os::raw::c_int; 2usize] = [3, 4];

I figure that cases like MACRO_ARRAY are difficult in general, relating to issues like #316. But if at least the static_const_array case would work, it could be used as a simple workaround for the macro support.

Workaround

As it is, one has to write and compile some C (typically involving the cc crate) that provides a symbol to hold the array value, and in the non-macro case a way of initializing it because C can't do it at compile time. For example:

#include <string.h>
#define MACRO_ARRAY {1, 2}
static const int static_const_array[] = {3, 4};

const int my_macro_array[] = MACRO_ARRAY;

int my_static_const_array[sizeof(static_const_array) / sizeof(static_const_array[0])];
void my_static_const_array_init(void) {
   memcpy(my_static_const_array, static_const_array, sizeof static_const_array);
}

And then in the bindgen stub declare e.g.:

const int my_macro_array[sizeof((int[])MACRO_ARRAY) / sizeof(int)] = MACRO_ARRAY;

extern int my_static_const_array[sizeof(static_const_array) / sizeof(static_const_array[0])];
extern void my_static_const_array_init(void);

And finally, arrange a way of calling my_static_const_array_init when needed.

Needless to say, this is quite painful. :-) I'm open to better approaches, this is just the most straightforward thing off the top of my head.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the bindgen input.h case containing MACRO_ARRAY and static_const_array, then inspect how the invocation emits the shown Rust declarations. Compare the generated output with the expected array definitions and determine what completion should cover for static arrays versus macro-defined arrays; the issue provides no specific source file or test path.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, rust
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.