Передайте черту ржавчины в C
Я строю библиотеку Rust, которая должна вызывать некоторые функции C с объектами Rust. У меня есть черта с функцией, которая вызывает функцию C, функция C определяется в Rust следующим образом:
extern {
fn process_trait(my_trait: MyTrait);
}
Идея состоит в том, что пользователь может реализовать признак для своей структуры и затем вызвать функции C (в основном, C затем вызывает некоторый другой Rust, который вызывает некоторые функции Trait). Ошибка здесь: the trait core::marker::Sized is not implemented for the type Self
потому что я прохожу *self
обработать Я делаю что-то неправильно? Я попытался изменить это немного, даже приведение, я получаю или эту ошибку или неправильный тип.
Я думаю, проблема в том, что он должен быть выделен кучей, нет? Единственное, чего я пытаюсь избежать, это API, который выглядит ужасно. Пользователь должен просто иметь возможность
struct MyUnit;
impl MyTrait for MyUnit...
MyUnit.callC();
1 ответ
Передавать объект trait по значению не имеет смысла, особенно при взаимодействии с C. Фактический тип (в смысле C) и его размер неизвестны, и внутри объекта нет vtable. Скорее всего, вы хотите передать характеристику (&MyTrait
). Тем не менее, черты чужды C и, следовательно, делают плохой интерфейс. Хотя вы могли бы определить эквивалент core::raw::TraitObject
в C делать что-либо с помощью vtable крайне уродливо, хрупко и небезопасно.
Если вам нужен полиморфизм через барьер Rust-C, явные указатели на функции являются гораздо лучшим вариантом. Вы все еще можете иметь MyTrait
и callC
метод, это просто части FFI, которые выглядят иначе. Может быть возможно передать обратные вызовы библиотеки C с объектами в качестве полезной нагрузки.
В качестве альтернативы, обойти вышеупомянутое TraitObject
s (толстые указатели), но никогда не проверяйте их из C, вызывайте методы через (не-trait) вспомогательную функцию в Rust:
extern fn call_method(obj: TraitObject) {
let obj: &MyTrait = transmute(obj); // should be safe, but not tested
obj.meth();
}
Это позволяет избежать проблем, возникающих при копании вручную через Rust vtable в C.