我在我与包裹在一个数据工作的情况Arc,我有时最终使用into_raw,以获得原始指针的基础数据。我的用例还需要类型擦除,因此原始指针通常被强制转换为 a *const c_void,然后在重新构造Arc.
我遇到过这样一种情况,即能够在Arc不需要知道底层数据的具体类型的情况下克隆它会很有用。据我了解,只要我从未真正取消引用数据,Arc仅出于调用目的而使用虚拟类型重建 应该是安全clone的。因此,例如,这应该是安全的:
pub unsafe fn clone_raw(handle: *const c_void) -> *const c_void {
let original = Arc::from_raw(handle);
let copy = original.clone();
mem::forget(original);
Arc::into_raw(copy)
}
Run Code Online (Sandbox Code Playgroud)
有什么我遗漏的东西会使这实际上不安全吗?另外,我认为答案也适用于Rc,但如果有任何差异,请告诉我!
在 Rust 中执行 FFI 时()(或任何其他零大小类型)的等价物是什么?具体来说,我很好奇()在编写extern "C"函数时作为函数参数最合理的等价物是什么。
我的理解是零大小类型在 C 中无效,但 Rust 似乎允许在extern "C"函数中使用它们,例如:
#[no_mangle]
pub extern "C" fn test_ffi(input: ()) -> () {
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,返回()与void在 C# 中声明函数相同。但是,我不清楚input在从 C 生成绑定时如何声明参数。我的印象是 ZST 不能在 C 中表示,因此不应该是 FFI 安全的。似乎nomicon 证实了这一点,说:
为了避免
()在 FFI 中使用时出现警告,我们改为使用空数组 ([u8; 0]),它与空类型一样有效,但与 FFI 兼容。
这似乎暗示这()不是 FFI 兼容的,但那[u8; 0]是(即使我希望它也是零尺寸)?