我什么时候应该在 C 库的 Rust 绑定中使用 `&mut self` 与 `&self`?
When should I use `&mut self` vs. `&self` in Rust bindings for a C library?
我不确定在 libzmq C API.
的 Rust 绑定中何时使用 &mut self
与仅使用 &self
一些背景知识:libzmq 提供了套接字"objects",它有一个类似于BSD套接字API的API,在C中用一个不透明的指针表示。这个指针实际上只是一个句柄,类似于 POSIX 文件描述符,并且 C API 的设计使得它 not 不可能获得对它背后的内存的任何引用指针。
在这种情况下,API 设计使用不可变 self
公开套接字方法是否安全且良好?作为具体示例,请考虑 zmq_send()
:
int zmq_send (void *socket, void *buf, size_t len, int flags);
我认为它可以(并且应该)使用不可变的自我来公开,即:
pub fn send(&self, data: &[u8], flags: i32) -> Result<()> { ... }
然而,可比较的 Rust 标准库方法使用 &mut self
,例如std::io::Write::write()
,由 std::net::TcpStream
实施。另一方面,std::net::UdpStream::write()
只需要 &self
。我的猜测是 &mut self
被使用只是因为它是 Write
特征的实现,反过来(我猜)使用 &mut self
来不限制特征的实现。
我希望有人能在这里支持或反驳我的推测——我在本书或 Nomicon 中找不到关于该主题的任何具体内容。
在这种情况下对象是否发生变异是次要的;主要问题是"is it safe for two references to be used at the same time?"。两个线程同时调用同一对象上的 zmq_send
(或其他方法),或者(如果 API 允许)通过嵌套回调等,是否可以?
如果不是,请使用 &mut self
并让 Rust 执行您需要的安全保证。
如果安全的话,也许&self
是合适的,如果zmq
保证没问题;这就像 Mutex::lock
占用 &self
.
我不确定在 libzmq C API.
的 Rust 绑定中何时使用&mut self
与仅使用 &self
一些背景知识:libzmq 提供了套接字"objects",它有一个类似于BSD套接字API的API,在C中用一个不透明的指针表示。这个指针实际上只是一个句柄,类似于 POSIX 文件描述符,并且 C API 的设计使得它 not 不可能获得对它背后的内存的任何引用指针。
在这种情况下,API 设计使用不可变 self
公开套接字方法是否安全且良好?作为具体示例,请考虑 zmq_send()
:
int zmq_send (void *socket, void *buf, size_t len, int flags);
我认为它可以(并且应该)使用不可变的自我来公开,即:
pub fn send(&self, data: &[u8], flags: i32) -> Result<()> { ... }
然而,可比较的 Rust 标准库方法使用 &mut self
,例如std::io::Write::write()
,由 std::net::TcpStream
实施。另一方面,std::net::UdpStream::write()
只需要 &self
。我的猜测是 &mut self
被使用只是因为它是 Write
特征的实现,反过来(我猜)使用 &mut self
来不限制特征的实现。
我希望有人能在这里支持或反驳我的推测——我在本书或 Nomicon 中找不到关于该主题的任何具体内容。
在这种情况下对象是否发生变异是次要的;主要问题是"is it safe for two references to be used at the same time?"。两个线程同时调用同一对象上的 zmq_send
(或其他方法),或者(如果 API 允许)通过嵌套回调等,是否可以?
如果不是,请使用 &mut self
并让 Rust 执行您需要的安全保证。
如果安全的话,也许&self
是合适的,如果zmq
保证没问题;这就像 Mutex::lock
占用 &self
.