Если точнее:
- Когда структура C++ уничтожается, вызывается деструктор (), а затем поля уничтожаются в обратном порядке объявления.
Код: Выделить всё
T::~T() - Когда структура Rust удаляется, вызывается Drop::drop(), а затем поля удаляются в порядке объявления.
Предположим, у меня есть структура в Rust:
Код: Выделить всё
#[repr(C)]
pub struct MyStruct {
field: AnotherStruct
}
#[repr(C)]
pub struct AnotherStruct {
something: *mut i32
}
impl Drop for MyStruct {
// ...
}
impl Drop for AnotherStruct {
// ...
}
Код: Выделить всё
struct AnotherStruct {
int32_t *something;
~AnotherStruct() {
// what to put here
}
};
struct MyStruct {
AnotherStruct field;
~MyStruct() {
// what to put here
}
};
Rust:
Код: Выделить всё
unsafe extern "C" {
pub fn test(object: MyStruct);
}
Код: Выделить всё
extern "C" {
void test(MyStruct object) {
// use `object`...
}
}
В идеале из C++ я должен:
- вызвать MyStruct::drop() в MyStruct::~MyStruct()
- позволим C++ вызвать деструктор поля
- вызвать AnotherStruct::drop() в AnotherStruct::~AnotherStruct()
- позволить C++ вызвать деструктор ptr (что является пустой операцией).
Поэтому мне нужно намеренно игнорировать выполнение drop_in_place(). Однако, похоже, в Rust невозможно вызвать Drop::drop() без связующего звена.
Обратите внимание, что проблема возникает только потому, что я пытаюсь переместить структуру во внешнюю функцию "C". Если я передаю что-то по ссылке, я могу свободно использовать std::ptr::drop_in_place(), потому что деструкторы C++ вообще не будут работать. Но это именно то, что я хочу/нужно сделать.
Некоторые очевидные решения для меня неприемлемы, в частности:
- Я не могу изменить API экспортируемых структур Rust, поэтому я не могу изменить поле: AnotherStruct для поля: ManuallyDrop
- На На стороне C++ я могу избежать запуска деструкторов поля, обернув поле в объединение, например:
Код: Выделить всё
struct MyStruct {Код: Выделить всё
union { AnotherStruct field; } field_u;но тогда мне нужно будет использовать поле как object.field_u.field вместо object.field, и мне нужно этого избегать.Код: Выделить всё
};
Подробнее здесь: https://stackoverflow.com/questions/798 ... uct-fields
Мобильная версия