curl - 为什么这个堆栈变量不需要移到闭包中?

标签 curl rust

我想了解为什么下面示例中的外部堆栈变量 data 不需要与闭包一起使用 move 关键字。

示例取自Curl crate ,以及 documentation声明 write_function 的生命周期取自 transfer 变量,因此闭包可以访问堆栈变量 data 而无需移动它.

以下是文档中的引用:

Note that the lifetime bound on this function is 'static, but that is often too restrictive. To use stack data consider calling the transfer method and then using write_function to configure a callback that can reference stack-local data.

参见:https://docs.rs/curl/0.4.6/curl/easy/struct.Easy.html#method.write_function

use curl::easy::Easy;

let mut data = Vec::new();
let mut handle = Easy::new();
handle.url("https://www.rust-lang.org/").unwrap();
{
    let mut transfer = handle.transfer();
    transfer.write_function(|new_data| {
        data.extend_from_slice(new_data);
        Ok(new_data.len())
    }).unwrap();
    transfer.perform().unwrap();
}
println!("{:?}", data);

为什么会这样?

或者,如果我尝试直接使用 handle 中的 write_function,则会出现借用错误,指出 data 已被移动。

这是一个不起作用的例子,我明白为什么它不起作用。我很困惑为什么上面的方法会起作用。

use curl::easy::Easy;

let mut data = Vec::new();
let mut handle = Easy::new();
handle.url("https://www.rust-lang.org/").unwrap();
handle.write_function(move |new_data| {
   data.extend_from_slice(new_data);
   Ok(new_data.len())
}).unwrap();
handle.perform().unwrap();
println!("{:?}", data);
//               ^^^^ error because it was moved

最佳答案

您引用的curl文档来自curl::easy::Easy::write_function方法。正如所描述的,这个函数采用一个具有'static生命周期界限的闭包——换句话说,它必须在程序的持续时间内持续存在。

这意味着此类闭包借用的任何值都永远无法返回,因为闭包永远不会超出范围。

这与curl rust 库包装curl C 库这一事实有关,而C 库的工作原理是允许调用者为各种事件注册回调函数。在将闭包作为回调函数传递给 C 库后,Rust 编译器无法跟踪闭包的生命周期,因此唯一可以使用的安全生命周期是 'static

为了解决这个问题,curl 模块提供了 Transfer对象,您可以向其注册生命周期小于 'static 的闭包。 Transfer 对象负责在底层 C 库中注册和取消注册回调,并尊重它们的生命周期。

了解了这一点后,请考虑您的示例代码:

{
    let mut transfer = handle.transfer();
    transfer.write_function(|new_data| {
        data.extend_from_slice(new_data);
        Ok(new_data.len())
    }).unwrap();
    transfer.perform().unwrap();
}

在这里,闭包可变地借用了数据。闭包被传递给transfer.write_function,这要求它与传输对象本身一样持续。因此,data 会被借用,直到声明 transfer 的 block 末尾为止。

关于curl - 为什么这个堆栈变量不需要移到闭包中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58584118/

相关文章:

php - 尝试安装 Composer 时出现 SSL 证书错误

rust - 将 `Vec<u16>` 内容写入文件的正确方法是什么?

rust - 闭包签名的强制/强制评估

types - 在 Rust 中声明 2D、3D 矢量类型的惯用方法?

multithreading - 从线程中获取 HashMap

rust - 需要拥有 self 所有权的典型用例是什么?

curl - 如何在 Postman 中使用 GitHub API

http - Nagios check_http 为 HAProxy 站点提供 'HTTP/1.0 503 Service Unavailable'

php - 避免 cURL 调用之间的网络问题

php - 客户端-服务器架构决策