I'm currently working on building an Nginx module in Rust, and the existing C code is resulting in some awkward Rust code when run through Bindgen. For example:
#define NGX_OK 0
#define NGX_ERROR -1
produces
pub const NGX_OK: i32 = 0;
pub const NGX_ERROR: i32 = -1;
But it's used in functions with a return type of
ngx_int_t function_name(...)
Where ngx_int_t
is defined as
typedef intptr_t ngx_int_t;
typedef __darwin_intptr_t intptr_t;
typedef long __darwin_intptr_t;
Or, in Rust:
pub type ngx_int_t = isize;
Which results in type errors when trying to return NGX_OK
from a function.
Another fun example is:
#define NGX_CONF_OK NULL
#define NGX_CONF_ERROR (void *) -1
Which, for reasons that are unclear to me, is returned as char * function_name(...)
, or function_name(...) -> *mut ::std::os::raw::c_char
in Rust.
Perhaps unsurprisingly, neither of those #define
statements result in Rust constants.
Another one that's annoying is #define
s like this:
#define NGX_MODULE_SIGNATURE_1 "1"
Which, quite reasonably, translate into
pub const NGX_MODULE_SIGNATURE_1: &[u8; 2usize] = b"1\0";
In Rust, but these particular constants are meant to be used by other #define
directives to build the actual String constant, so I wind up doing something like this to get the data I need from them:
NGX_MODULE_SIGNATURE_1[0] - 48
What do people do in similar situations? I can see a few options:
- Exclude the constants from automatic generation, and add them in manually with the right types. Easy to do, but doesn't scale if there's a lot of these situations (which I suspect is the case)
- Use the C2Rust refactoring tool (or
sed
or something similar) as part of the build process to automatically refactor this in the generated sources - Leave it as-is and accept that it's going to be a pain to use