Definitions of static or macro-defined arrays are not emitted
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.
The clang constant evaluation stuff doesn't work for arrays at all afaict, so this would need upstream changes to libclang to be fixable.
You're right. I filed it upstream: https://bugs.llvm.org/show_bug.cgi?id=36576
Otherwise, I suppose #297 would provide a fix, but it's a bigger undertaking.
Sharing that the LLVM bug moved to github: https://github.com/llvm/llvm-project/issues/35924
I've run into this bug as well, where some constant structures are defined in headers. Would really like to not have to manually copy that data over
Eg: Definition in header: https://github.com/giantcow/nvcodec-rust/blob/294813153b80fad3984c1fde065469f104b19eb2/nvenc-sys/include/nvEncodeAPI.h#L140-L141 bindgen blocklist: https://github.com/giantcow/nvcodec-rust/blob/294813153b80fad3984c1fde065469f104b19eb2/nvenc-sys/build.rs#L19 Manual definition: https://github.com/giantcow/nvcodec-rust/blob/294813153b80fad3984c1fde065469f104b19eb2/nvenc-sys/src/lib.rs#L25-L30
I found an ugly workaround, but it works without manually copying anything. In my case, I needed to generate this PFRES_NAMES macro. The values can be obtained via the ParseCallbacks::modify_macro method and appended to the generated file. A complete example is in this build.rs.