I am building a Rust library that needs to call some C functions with Rust objects. I have a trait with a function that calls the C function, the C function is defined in Rust as follows:
extern {
fn process_trait(my_trait: MyTrait);
}
The idea is that the user can implement the trait for his struct and then call the C functions (basically, the C then calls some other Rust back, which calls some of the Trait functions). The error here is: the trait core::marker::Sized is not implemented for the type Self
, because I am passing *self
to process_trait. Am I doing something wrong? I tried changing this a bit, even casting, I am getting either this error or wrong type.
I think the problem is that it's supposed to be heap allocated, no? The only thing I am trying to avoid is the API looking ugly. The user should just be able to
struct MyUnit;
impl MyTrait for MyUnit...
MyUnit.callC();
Passing a trait object by value doesn't make sense, especially when interacting with C. The actual type (in the C sense) and its size is not known, and there's no vtable inside the object. You most likely want to pass a trait reference (
&MyTrait
). However, traits are foreign to C and thus make a bad interface. While you could define the equivalent ofcore::raw::TraitObject
in C, actually doing anything with the vtable is extremely ugly and fragile and unsafe.If you need polymorphism across the Rust-C barrier, explicit function pointers are a much better option. You can still have
MyTrait
and thecallC
method, it's just the FFI parts that look different. It may be possible to hand the C library callbacks with the objects as payload.Alternatively, pass around the aforementioned
TraitObject
s (fat pointers) but never inspect them from C, call methods through (non-trait) helper function in Rust:This avoids the trouble that is manually digging through a Rust vtable in C.