I'm working on a Rust library that is used from C. I have an enum that is used to represent errors. I would like to automatically generate a header file with constants for each of the enum variants. That way the Rust code can return an integer (by converting the enum variant to an int), and the C program can use that to determine the error message.
I was wondering if this is possible, or do I need to manually generate the constants in the header file?
Furthermore, I'm not sure how to convert the enum into an integer. This only seems possible for simple enums.
For generating C headers based on your Rust code, you probably want cbindgen.
By "simple enum", I suppose you mean enums with only unit variants (i.e. no associated data). Of course, enums with associated data can't be expressed as primitive integers – how would you plan to expose the associated data in those cases?
I only care about the "number" the enum variant has. I will have a function that turns an enum variant into a string (to handle enums with associated data), but I still want to get an integer code that the C code can check.
I checked cbindgen, but I don't think it can declare constants.
Here's an example of what I'm trying to do:
if (error < 0) {
if (error == GIT_ENOTFOUND)
fprintf(stderr, "Could not find repository at path '%s'\n", path);
else
fprintf(stderr, "Unable to open repository: %s\n",
git_error_last()->message);
exit(1);
}
Alas, the enum I have is autogenerated using proc macros, so I don't think it's straightforward to apply the proc macro to it.
// Use `EnumDiscriminants` to get an integer code for each enum variant
// https://users.rust-lang.org/t/rust-c-ffi-declare-constants-from-enums/60082/3
#[derive(Error, Debug, EnumDiscriminants)]
pub enum FooError {
#[error("yadda yadda....")]
Oh, I see, that's indeed quite restrictive. Luckily, safer-ffi, contrary to cbindgen, is robust to macros, provided derive_ReprC annotation is emitted by the macro. Since EnumDiscriminants won't do that for us, we can polyfill it: