Pointers 内部可变结构的原始指针类型
我正在为Erlang NIF API做一些Rust FFI工作,我有: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; 但是,我认为我可以将这种类型视为具有“内部可变性”,这将导致
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签名