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
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 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
#defines 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 - 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
sedor 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