Pointers 内部可变结构的原始指针类型

Pointers 内部可变结构的原始指针类型,pointers,rust,ffi,erlang-nif,Pointers,Rust,Ffi,Erlang Nif,我正在为Erlang NIF API做一些Rust FFI工作,我有: ErlNifEnv *enif_alloc_env(); void enif_free_env(ErlNifEnv* env); 这个ErlNifEnv指针会被传递给其他各种函数,但用户永远不会取消对指针的引用。此外,此指针不是线程安全的(在多个线程之间使用需要互斥)。这种类型的朴素锈蚀表示为 struct ErlNifEnv; *mut ErlNifEnv; 但是,我认为我可以将这种类型视为具有“内部可变性”,这将导致

我正在为Erlang NIF API做一些Rust FFI工作,我有:

ErlNifEnv *enif_alloc_env();
void enif_free_env(ErlNifEnv* env);
这个ErlNifEnv指针会被传递给其他各种函数,但用户永远不会取消对指针的引用。此外,此指针不是线程安全的(在多个线程之间使用需要互斥)。这种类型的朴素锈蚀表示为

struct ErlNifEnv;
*mut ErlNifEnv;
但是,我认为我可以将这种类型视为具有“内部可变性”,这将导致

struct ErlNifEnv;
*const ErlNifEnv;

即使底层C代码将其视为非常量,我是否应该将该指针视为常量?

我个人认为,您应该像对待Rust本身中的引用一样对待它们。当函数需要
&mut
引用时,它很可能会实际更改值,如果它需要
&mut
,则很自然地期望值不会更改(当然,忽略内部的可变性)


C在继承和内部易变性之间没有区别,因此您可以仅根据C函数如何使用此值来选择使用
*mut
*const
。事实上,在正确编写的C API中,这种区别将以
const
限定符的形式出现。因此,如果有任何函数想要改变值,请使用
*mut
。如果没有此类函数(例如,这是一个只创建一次的不可变结构),请使用
*const
。当然,这适用于您希望存储在包装器中的类型—在FFI函数签名中,您应该始终镜像C API签名。

我个人认为,您应该像对待Rust本身中的引用一样对待它们。当函数需要
&mut
引用时,它很可能会实际更改值,如果它需要
&mut
,则很自然地期望值不会更改(当然,忽略内部的可变性)


C在继承和内部易变性之间没有区别,因此您可以仅根据C函数如何使用此值来选择使用
*mut
*const
。事实上,在正确编写的C API中,这种区别将以
const
限定符的形式出现。因此,如果有任何函数想要改变值,请使用
*mut
。如果没有此类函数(例如,这是一个只创建一次的不可变结构),请使用
*const
。当然,这适用于您希望存储在包装器中的类型—在FFI函数签名中,您应该始终镜像C API签名。

我个人认为,您应该像对待Rust本身中的引用一样对待它们。当函数需要
&mut
引用时,它很可能会实际更改值,如果它需要
&mut
,则很自然地期望值不会更改(当然,忽略内部的可变性)


C在继承和内部易变性之间没有区别,因此您可以仅根据C函数如何使用此值来选择使用
*mut
*const
。事实上,在正确编写的C API中,这种区别将以
const
限定符的形式出现。因此,如果有任何函数想要改变值,请使用
*mut
。如果没有此类函数(例如,这是一个只创建一次的不可变结构),请使用
*const
。当然,这适用于您希望存储在包装器中的类型—在FFI函数签名中,您应该始终镜像C API签名。

我个人认为,您应该像对待Rust本身中的引用一样对待它们。当函数需要
&mut
引用时,它很可能会实际更改值,如果它需要
&mut
,则很自然地期望值不会更改(当然,忽略内部的可变性)

C在继承和内部易变性之间没有区别,因此您可以仅根据C函数如何使用此值来选择使用
*mut
*const
。事实上,在正确编写的C API中,这种区别将以
const
限定符的形式出现。因此,如果有任何函数想要改变值,请使用
*mut
。如果没有此类函数(例如,这是一个只创建一次的不可变结构),请使用
*const
。当然,这适用于要存储在包装器中的类型——在FFI函数签名中,您应该始终镜像C API签名