使结构比赋予该结构的方法的参数更长寿

2024-03-03

我正在寻找一种方法来确保结构的寿命比赋予该结构的方法的参数的寿命长。 即使结构在离开方法后不保存对该数据的引用。

这是用于馈送到 FFI 的包装原始指针。我想保证实现 FFI 的结构比Option<&'a Any>我用来将 Rust 对象提供给指针包装器。

Context是 FFI 包装器。Data拥有映射到 FFI 类型的不同类型。 FFI 函数在返回之前立即复制所有这些类型。

原始指针除外。

所以我添加了一个生命周期说明符Context只是为了那些并使用它send_data().

但不知怎的,这还不够。我预计下面的代码无法编译。

编辑:Rust Discord 建议制作的某人&self mutable in send_data()。这达到了预期的效果,但我的 FFI 是线程安全的(且无状态的)并且send_data()时间紧迫。所以我非常想避免这种情况。

use std::any::Any;
use std::marker::PhantomData;

struct IntegerArray<'a> {
    data: &'a [i32],
}

struct WrappedRawPointer<'a> {
    ptr: *const std::ffi::c_void,
    _marker: PhantomData<&'a ()>,
}

impl<'a> WrappedRawPointer<'a> {
    fn new(data: Option<&'a dyn Any>) -> Self {
        Self {
            ptr: data
                .map(|p| p as *const _ as *const std::ffi::c_void)
                .unwrap_or(std::ptr::null()),
            _marker: PhantomData,
        }
    }
}

enum Data<'a, 'b> {
    IntegerArray(IntegerArray<'a>),
    WrappedRawPointer(WrappedRawPointer<'b>),
}

struct Context<'a> {
    ctx: u32,
    _marker: PhantomData<&'a ()>,
}

impl<'a> Context<'a> {
    fn new() -> Self {
        Self {
            ctx: 0, // Call FFI to initialize context
            _marker: PhantomData,
        }
    }

    fn send_data(&self, data: Data<'_, 'a>) {
        match data {
            Data::IntegerArray(_i) => (),      // Call FFI function
            Data::WrappedRawPointer(_p) => (), // Call FFI function
        }
    }
}

fn main() {
    let ctx = Context::new();

    {
        let some_float: f32 = 42.0;
        ctx.send_data(
            Data::WrappedRawPointer(
                WrappedRawPointer::new(
                    Some(&some_float)
                )
            )
        );

        // I would like rustc to complain 
        // here that some_float does not
        // outlive ctx
    }

    // Explicitly drop outside
    // the previous block to 
    // prevent rustc from being
    // clever
    drop(ctx);
}

Making send_data take &mut self代替&self之所以有效,是因为它使得类型self范围不变的关于类型Self. 子类型和方差 https://doc.rust-lang.org/nomicon/subtyping.htmlRustonomicon 中对此进行了描述,以及 Stack Overflow 上的其他问题(见下文)。

因为你想要不变性,即使self是一个不可变的引用,这表明Context<'a> itself是错误的:它是协变的'a,但它应该是不变的。您可以通过将类型参数更改为来解决此问题PhantomData到同样不变的东西'a:

struct Context<'a> {
    ctx: u32,
    _marker: PhantomData<*mut &'a ()>,  // or Cell<&'a ()>, or fn(&'a ()) -> &'a (), etc.
}

PhantomData不仅仅是为了让编译器不会对你大喊大叫而机械地添加的东西。类型参数的具体形式PhantomData告诉编译器how您的结构与其类型和生命周期参数相关(当编译器无法自行弄清楚时)。在这种情况下,您想告诉编译器Context<'some_long_lifetime> can't被替换为Context<'a_much_shorter_lifetime>即使它的字段都允许这种替换。

关于方差的更多问题

  • 这个实例如何看起来比它自己的参数生命周期还要长? https://stackoverflow.com/questions/42637911/how-can-this-instance-seemingly-outlive-its-own-parameter-lifetime
  • 为什么链接生命周期仅与可变引用相关? https://stackoverflow.com/questions/32165917/why-does-linking-lifetimes-matter-only-with-mutable-references
  • 如何在线程之间共享包含幻像指针的结构? https://stackoverflow.com/questions/50200197/how-do-i-share-a-struct-containing-a-phantom-pointer-among-threads(如果Context应该Send or Sync)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使结构比赋予该结构的方法的参数更长寿 的相关文章

随机推荐

  • 拒接来电的问题

    我尝试通过以下代码拒绝来电 private void ignoreCallAidl Context context try tm TelephonyManager context getSystemService Context TELEP
  • 在实例方法中从父级访问类属性

    我想从类继承链中的每个类中读取类属性 像下面这样 class Base object def smart word reader self for word in self words print word class A Base wor
  • 一个 XSD、两个代码生成工具、两个命名空间

    我有一个 XSD 文件 我还想从中生成 C 和 Java 类 我首先根据类所在的 C 命名空间在 XSD 中设置命名空间 生成 使用 Microsoft 工具 运行良好 序列化也运行良好 我可以根据 XSD 验证它们 完美 现在我想使用 J
  • 在更新中从 Stripe 订阅中删除优惠券

    我需要在更新期间删除订阅上的优惠券 我认为将 nil 优惠券传递给 api 应该将其删除 但它只是将其从帖子中删除 还有另一种方法可以这样做 https stripe com docs api discounts subscription
  • 验证失败后恢复输入类型=文件的值

    我有一个带有多个处理文件的输入的表单 javascript 验证非常擅长检查以确保一切正常 但有些事情需要 PHP 进行检查 例如文件的 mime 类型 有时会被拒绝 问题是 当我将用户发送回表单时 我可以重新填充他们最初输入的所有数据 但
  • EF Power Tools Beta 2 - 调用目标已引发异常

    我有 EF 5 0 代码优先 VS 2012 项目 并且所有实体框架菜单命令 查看实体数据模型 DDL SQL 都会生成 调用目标已引发异常 弹出窗口 我认为也发生了变化的是 EF Power Tools Beta 1 或 VS 2010
  • CSS“背景大小”属性 - 跨浏览器解决方案?

    我有一个使用这个 css 的元素 my box padding left 50px background image url images img01 png background size 20px height 20px 我的问题 在
  • RxJava 2.x 中带有背压的 PublishSubject

    我目前正在为我当前的项目选择 RxJava 1 x 或 2 x 我基本上需要一个PublishSubject采用背压策略onBackpressureLatest 我想选择 RxJava 2 x 但我不太清楚如何将反压策略应用于Publish
  • 使用 Dojo 从跨域的 ReST 服务检索 XML 数据

    我正在尝试为 ReST 应用程序编写一个基于浏览器的 Javascript 客户端 该应用程序使用 XML 进行响应 所以看来 JSONP 是不可能的 我正在尝试使用检索数据dojo io script get但传递给回调函数的参数是一个对
  • 佣金详情服务(REST)

    使用 CJ 佣金详细服务 REST 的人能否告诉我此查询的示例 XML 响应是什么 CJ 的 Web 服务文档都没有准确说明 XML 的格式 而且由于我没有任何佣金 所以我只能猜测结果 通过与我的出版商之一签约 我发现了一个艰难的方法
  • 在实现 IEnumerable 的类上序列化自定义属性[重复]

    这个问题在这里已经有答案了 目前 JSON NET 忽略实现 IEnumerable 的类上的所有其他属性并序列化数组 如何告诉 JSON NET 序列化自定义属性 我正在尝试序列化PagedList
  • CSS 中的倒圆角?

    我有一个CSS代码 moz border radius topleft 50px 我得到结果 是否有可能像这样给予 在现代浏览器中 您可以使用mask image aux container width 100px height 100px
  • 当服务器绑定到特定 IP(不是本地主机)时,如何使 Google App Engine python SDK Remote API 与本地开发服务器一起工作?

    使用远程 API remote api shell py 在生产服务器上运行良好 但是 它仅在开发服务器上运行时才有效localhost 当服务器在特定 IP 上运行时 例如 dev appserver py host 192 168 0
  • 使用串行蓝牙连接设备时出现问题

    我面临两个与常规蓝牙相关的问题 这是我的代码 void viewDidLoad super viewDidLoad NSTimer scheduledTimerWithTimeInterval 3 0 target self selecto
  • 如何调用 AngularJS 指令中定义的方法?

    我有一个指令 这是代码 directive map function return restrict E replace true template div div link function scope element attrs var
  • 在另一个窗口中打开另一个进程

    在我的代码中 我想在另一个 python 窗口中启动一个函数 脚本 例如 当您运行一个脚本时 会弹出一个后窗口 我希望该脚本管理其他脚本 它们不需要进行通信 与多处理类似 但它们有自己的弹出窗口和输出 他们的所有信息都将随后写入文件中 我已
  • 从 IEEditorPart (Eclipse) 获取 ITextViewer

    Eclipse RCP 问题 我用以下命令打开文件 IWorkbenchPage page PlatformUI getWorkbench getActiveWorkbenchWindow getActivePage IEditorPart
  • 数字倒着显示?

    当我看到用户的投诉时我不相信 在绑定的 WPF 文本框中键入 123 将显示 321 目前已修复 但我想知道这是否可以归类为 WPF bug 当文本框绑定到实体框架双字段且 UpdateSourceTrigger 绑定模式设置为 Prope
  • “启用”类比较[重复]

    这个问题在这里已经有答案了 我需要有关我的 CSC 硬件的帮助 它位于类 对象上 是一个定义圆的简单类 名称为 class Circle object 硬件的确切文本 我完成了该硬件的前两部分 因此第三部分是对初始问题的扩展 通过使用 gt
  • 使结构比赋予该结构的方法的参数更长寿

    我正在寻找一种方法来确保结构的寿命比赋予该结构的方法的参数的寿命长 即使结构在离开方法后不保存对该数据的引用 这是用于馈送到 FFI 的包装原始指针 我想保证实现 FFI 的结构比Option lt a Any gt 我用来将 Rust 对