Да, это безопасно.Я бы написал это так:
use std::ptr;
fn safe_wrapper(opt: Option<&u8>) {
let p = opt.map_or_else(ptr::null, |x| x);
unsafe { ffi_call(p) }
}
Если вы обнаружите, что пишете это много, вы можете превратить это в черту и сократить до одного вызова метода.
указатель может быть признан недействительным, поскольку он проходит через замыкание
Это может быть, если вы каким-либо образом его аннулируетеПоскольку функция берет ссылку, вы точно знаете, что указанное значение будет действительным в течение всего времени вызова функции - это цель средства проверки заимствования в Rust.
Единственный способ, которым указатель становитсяНедопустимо, если вы измените значение указателя (например, вы добавите к нему смещение).Поскольку вы этого не делаете, это нормально.
Гарантирует ли Rust, что окончательный указатель будет указывать на то же, что и исходная ссылка?
Это зависит от того, что вы подразумеваете под "финалом".Преобразование ссылки на указатель всегда приведет к тому, что оба значения будут содержать одно и то же место в памяти.Все остальное было бы преднамеренно злонамеренным, и никто бы никогда не использовал Rust для начала.
Если T
равно Copy
, значит ли это изменить семантику значимым образом?
Нет.Кроме того, речь идет о &T
, то есть всегда Copy
См. Также:
используемый мной интерфейс FFI имеет семантику заимствования (я выделяю что-то и передаю указатель на него ), а не семантика владения
Чтобы было ясно, вы не можете определить владение исключительно на основе типов функций.
Эта функция C становится владельцем:
void string_free(char *)
Эта функция C занимает:
size_t string_len(char *)
Оба указателя имеют указатель.Rust улучшает эту ситуацию, четко разграничивая, что такое заем и передача права собственности.
extern "C" {
// Parameter may be null
fn ffi_call(*const T);
}
Этот код не имеет смысла;он не определяет универсальный тип T
, и функции FFI в любом случае не могут иметь универсальные типы.