让我们考虑一下围绕C库的Rust包装器库。这个C库定义了一个结构,并将其用作整个API的可变指针。
Rust包装器定义了以下结构,其中ptr
指向data
。
struct Wrapper {
data: struct_from_c_t,
ptr: *mut struct_from_c_t,
}
如果此指针的所有使用都在Wrapper
结构的生存期内进行,那么在不安全的代码中使用此指针时,还会遇到其他潜在问题吗?
在此构造中取消引用和使用此指针是否总是安全的?
详细情况下,目标是能够使用此指针从不可更改地借用Wrapper
的函数中调用此FFI函数。
答案 0 :(得分:3)
这通常是一个坏主意,并且可能非常容易出错。
首先,请阅读Why can't I store a value and a reference to that value in the same struct?,深入了解为何安全Rust会在编译时阻止此构造。
TL; DR,如果您曾经移动func didSelect(_ segmentIndex: Int) {
showHome.isHidden = segmentIndex != 0
showProfile.isHidden = segmentIndex != 1
showSettings.isHidden = segmentIndex != 2
// if you need to run other code based on the selected segment
switch segmentIndex
{
case 0:
// SHOWING THE HOME VIEW
// do other stuff here...
case 1:
// SHOWING THE PROFILE VIEW
// do other stuff here...
case 2:
// SHOWING THE SETTINGS VIEW
// do other stuff here...
default:
break;
}
}
结构,则指针将无效。取消引用它会导致未定义的行为(一件坏事)。
如果您可以确保以下任何一项:
Wrapper
永远不会移动。Wrapper
都会更新。然后,该指针将是有效且可以安全地取消引用(假定所有其他有关不安全代码的警告均得到保留)。
更糟糕的是,没有 reason 将指针放在首位;您可以在需要时引用一个值并将其转换为指针:
ptr
从函数中不可更改地借用
extern "C" { fn ffi_fn(data: *mut struct_from_c_t); } struct Wrapper { data: struct_from_c_t, } impl Wrapper { fn do_thing(&mut self) { unsafe { ffi_fn(&mut self.data) } } }
在没有上下文的情况下,这似乎是一个可疑的决定,但是Rust具有用于内部可变性的工具:
Wrapper