Open stephan57160 opened 2 years ago
This issue is mainly due to the fact that size of "C enum" is an implementation defined according to the C standard.
So generated "C API" get and return integers instead of enum, and C++ convert it from/into enum.
So while flapigen
can generate "C enum" it is useless because of C functions should get/return fixed size integers anyway.
It is obviously possible to generate C inline function that wrap C functions and take care of conversions enum<->integer, but this looks like overkill.
Agreed for the enum returned by C. The current C++ implemantation is rather similar to what could be done for C :
enum FOO {
FOO_xxx = 0,
FOO_yyy = 1,
...
};
It's also convenient, as RUST can convert ENUM to any INT. It's not true from INT to ENUM, though.
At least, this solves the situation where a RUST function returns an Error :
fn MyRustFunction() -> Error {...}
and the C code performs a switch ... case on returned value :
ret = MyRustFunction();
switch (ret) {
case xxx :
...
}
Hmm ... I may need some guidance, to write some test case(s), if you don't mind, for a PR.
The creation of expectation test would be rather simple.
foreign_enum!(enum Boo { A = Boo::A, B = Boo::B });
cenum.cpp
file near cenum.rs
, with C code that you expect to flapigen
generate,
in form of string literals separated by ";" cargo test --release
, "release" because of debug build to slow.In spite of name fenum.cpp
may contains C and C++
OK. Thx. I'll have a look this afternoon.
From glue.rs.in code below :
foreign_enum!(
enum SomeEnum {
Val1 = SomeEnum::Val1,
Val2 = SomeEnum::Val2,
Val3 = SomeEnum::Val3,
}
);
foreign_class!(class Foo {
fn return_is_enum() -> SomeEnum;
fn param_is_enum(e: SomeEnum);
fn param_and_return_are_enum(e: SomeEnum) -> SomeEnum;
});
I'm able to generate something like :
enum SomeEnum {
SomeEnum_Val1 = 0,
SomeEnum_Val2 = 1,
SomeEnum_Val3 = 2,
};
typedef enum SomeEnum SomeEnumOpaque;
This part could be considered as complet :-)
Now, I wanted the C functions to use this new type. So, I wandered in flapigen code and ...
OK. I suppose that the following generated code
uint32_t Foo_return_is_enum();
void Foo_param_is_enum(uint32_t e);
uint32_t Foo_param_and_return_are_enum(uint32_t e);
is generated by RUSTC itself, based on cpp_glue.rs:
#[allow(non_snake_case, unused_variables, unused_mut, unused_unsafe)]
#[no_mangle]
pub extern "C" fn Foo_return_is_enum() -> u32 {
let mut ret: SomeEnum = return_is_enum();
let mut ret: u32 = <u32>::swig_from(ret);
ret
}
...
Now, I understand your statment It is obviously possible to generate C inline function that wrap C functions and take care of conversions enum<->integer, but this looks like overkill.
...
Then ... I guess that there is no way to have something like
SomeEnumOpaque Foo_return_is_enum();
void Foo_param_is_enum(SomeEnumOpaque e);
SomeEnumOpaque Foo_param_and_return_are_enum(SomeEnumOpaque e);
Moreover, I found that the C code is also used by the C++ one, to complicate a bit :-) OK. I'll leave the function part there.
Then, I also had a look to tests/expectations. It's rather simple to use. I was able to get some test with it.
I figured out that .hpp is generated to expose constants for enums, but this file is not usable for pure C code.
I worked a bit on that, this afternoon. I come to a
c_<enum_name>.h
that I'm able to include in a simple C code. But, its also a bit redundant with the already generated<enum_name>.hpp
.I'd like to discuss this, before raising a PR.