PhantomPinned 成员会使我的结构具有固定的内存地址吗?
Will a PhantomPinned member make my struct have a fixed memory address?
我正在编写与 C API 通信的 Rust 代码,我需要某个结构来拥有固定的内存地址。到目前为止,我发现:
Pin
用于指针;
pin_mut
固定在堆栈上的宏;
PhantomPinned
,我不清楚。
如果我理解正确,PhantomPinned
将是最容易使用的:将它作为成员将使我的结构自动具有固定的内存地址。这是正确的吗?
你需要的是Pin
。它是一个指针,可以防止您的对象被移动。
pin_mut!()
只是一个宏,可以帮助您创建一个 Pin
实例,无需堆分配或 unsafe
代码。
PhantomPinned
还有一个相关的目标。默认情况下,您的类型将实现 Unpin
特征(除非它包含不实现 Unpin
的类型,但大多数类型都实现)。这是有问题的,因为对于实现 Unpin
的类型,Pin
没有效果:它不会阻止您移动它们。这是因为大多数类型不需要固定的内存地址。想想 i32
,例如:即使你创建了 Pin<&mut i32>
,你也可以移动它,因为 i32
实现了 Unpin
,因为即使你移动它也没有什么坏处发生,并且不会验证任何数据。
因此,要使 Pin
有效,您需要 un-impl Unpin
。这是通过包含一个不实现 Unpin
本身作为字段的字段,或者具有负面影响(参见 )来完成的:
impl !Unpin for MyType {}
不幸的是,负面影响是不稳定的。相反,标准库提供了 PhantomPinned
类型,它是无成本的(一个 ZST),但没有实现 Unpin
(它有一个负面影响,因为标准库被允许使用不稳定的特性它可以做到)。现在,当您的类型包含它时,它也会变成 !Unpin
。
综上所述,您需要在结构中包含 PhantomPinned
,这样它就不会是 Unpin
,并且您需要将它包裹在 Pin
中,这样它就无法移动。
Rust 中唯一不可移动的值是 Pin<T>
中的值,并且仅当 T
未实现 Unpin
.
时
T
可能是引用或某些智能指针类型,如 Box
或 Arc
,但需要 Pin
来指定该值可能不会移动。
Unpin
是为不关心它们是否被移动(即使它们被固定)的类型实现的特征。它是为所有成员都实现 Unpin
的所有类型自动实现的标记特征。 PhantomPinned
是一个简单的零大小类型,它 不 实现 Unpin
,因此可以将它添加到结构或枚举中以使其不会自动实现 Unpin
.
请注意,Unpin
仅与 Pin
包装值相关 - Pin
之外的值仍然可以移动。需要不移动值的操作应该采用 Pin<&mut T>
而不是 &mut T
.
pin_mut
是一个用于将堆栈值转换为固定指针的宏。这只是 known-safe 案例的一种便利,并没有真正发挥 Pin
的作用。
所以对于你的情况,听起来你的结构应该有一个 PhantomPinned
成员,并且它的所有操作都应该采用 pin-wrapped 引用。
我正在编写与 C API 通信的 Rust 代码,我需要某个结构来拥有固定的内存地址。到目前为止,我发现:
Pin
用于指针;pin_mut
固定在堆栈上的宏;PhantomPinned
,我不清楚。
如果我理解正确,PhantomPinned
将是最容易使用的:将它作为成员将使我的结构自动具有固定的内存地址。这是正确的吗?
你需要的是Pin
。它是一个指针,可以防止您的对象被移动。
pin_mut!()
只是一个宏,可以帮助您创建一个 Pin
实例,无需堆分配或 unsafe
代码。
PhantomPinned
还有一个相关的目标。默认情况下,您的类型将实现 Unpin
特征(除非它包含不实现 Unpin
的类型,但大多数类型都实现)。这是有问题的,因为对于实现 Unpin
的类型,Pin
没有效果:它不会阻止您移动它们。这是因为大多数类型不需要固定的内存地址。想想 i32
,例如:即使你创建了 Pin<&mut i32>
,你也可以移动它,因为 i32
实现了 Unpin
,因为即使你移动它也没有什么坏处发生,并且不会验证任何数据。
因此,要使 Pin
有效,您需要 un-impl Unpin
。这是通过包含一个不实现 Unpin
本身作为字段的字段,或者具有负面影响(参见
impl !Unpin for MyType {}
不幸的是,负面影响是不稳定的。相反,标准库提供了 PhantomPinned
类型,它是无成本的(一个 ZST),但没有实现 Unpin
(它有一个负面影响,因为标准库被允许使用不稳定的特性它可以做到)。现在,当您的类型包含它时,它也会变成 !Unpin
。
综上所述,您需要在结构中包含 PhantomPinned
,这样它就不会是 Unpin
,并且您需要将它包裹在 Pin
中,这样它就无法移动。
Rust 中唯一不可移动的值是 Pin<T>
中的值,并且仅当 T
未实现 Unpin
.
T
可能是引用或某些智能指针类型,如 Box
或 Arc
,但需要 Pin
来指定该值可能不会移动。
Unpin
是为不关心它们是否被移动(即使它们被固定)的类型实现的特征。它是为所有成员都实现 Unpin
的所有类型自动实现的标记特征。 PhantomPinned
是一个简单的零大小类型,它 不 实现 Unpin
,因此可以将它添加到结构或枚举中以使其不会自动实现 Unpin
.
请注意,Unpin
仅与 Pin
包装值相关 - Pin
之外的值仍然可以移动。需要不移动值的操作应该采用 Pin<&mut T>
而不是 &mut T
.
pin_mut
是一个用于将堆栈值转换为固定指针的宏。这只是 known-safe 案例的一种便利,并没有真正发挥 Pin
的作用。
所以对于你的情况,听起来你的结构应该有一个 PhantomPinned
成员,并且它的所有操作都应该采用 pin-wrapped 引用。