我想在Rust中为C库创建安全接口.该库提供了一个生成器函数,该函数可以在某些源代码上多次调用(例如,文件)指针产生指向该源的后续元素的指针--基本上它是一个迭代器.

可以使用该元素指针做一些有用的事情,但在再次调用生成器函数后,前一个指针变得无效.元素也可以安全地克隆(这就是我现在使用的),但这会带来显著的性能损失,这在许多用例中是完全不必要的.

我想创建一个类似于C接口的安全包装器接口.我现在的 idea 是,我用struct Element包装元素指针,用struct Source包装源指针,它也保存当前有效的Element.

struct Source {
    current_element: Element,
    source_pointer: *mut S,
}

// things can be done with &Element directly
// or it can be safely cloned to Element
struct Element {
    element_pointer: *mut E,
}

为了包装生成器行为,我想为Source实现IteratorforSource,它在每次迭代中生成新的ELEMENT_POINTER,包装它,赋值给Source,并返回对current_element的引用,该引用只在.next()被再次调用之前有效.大概是这样的:

impl Iterator for Source {
    type Item = &Wrapper;

    fn next(&mut self) -> Option<Self::Item> {
        let new_pointer = unsafe{generator_ffi_function(self.source_pointer)};

        if new_pointer.is_null() {
            None
        } else {
            self.current_wrapper.element_pointer = new_pointer;
            Some(&self.current_wrapper)
        }
    }
}

但我无法解决如何在这种情况下使用生命周期.预期的接口可以在Rust中实现吗?如果可以,如何实现?

This solution是行不通的,因为当string_holder&'a mut打破的时候.This example包装了类似的C接口,但返回指针,因此不安全.许多问题也涉及实现可变迭代器,但我不想给出&mut个,这些解决方案还假设只有一个引用存在,这一点我不能保证.

推荐答案

这正是我们讨论了很多次的所谓"借出迭代器"或"流媒体迭代器".到目前为止,还没有对它们的语法语言支持,比如for循环,但是现在可以编写LendingIterator特征,因为泛型关联类型已经稳定(甚至在更早的时候):

pub trait LendingIterator {
    type Item<'a>
    where
        Self: 'a;

    fn next(&mut self) -> Option<Self::Item<'_>>;

    // Adapter methods...
}

这种特性是由lending-iterator箱提供的(尽管没有GATS),但是如果您想要的只是一个迭代器类型,那么只定义一个固有的next()方法会更简单.它可以用while let循环进行迭代:

let mut iter = ...;
while let Some(v) = iter.next() {
    // ...
}

不过,你确实弄丢了适配器.

C++相关问答推荐

获取二维数组的最大元素

如何用C(使用两个s补数算术的32位程序)计算

如何创建由符号组成的垂直结果图形?

为什么在C中二维字符数组会有这样的行为?

为什么net/if.h在ifaddrs.h之前?

在C23中使用_GENERIC实现带有右值的IS_POINTER(P)?

我怎么才能用GCC编译一个c库,让它包含另一个库呢?

在循环中复制与删除相同条件代码的性能

为什么此共享库没有预期的依赖项?

用C语言计算文本文件中的整数个数

I2C外设在单次交易后出现故障

#定义SSL_CONNECTION_NO_CONST

GCC奇怪的行为,有fork 和印花,有换行符和不换行符

如何用C语言为CLI应用程序编写按键检测系统?

将变量或参数打包到 struct /联合中是否会带来意想不到的性能损失?

在函数外部使用内联ASM时无法指定操作数

宏观;S C调深度

Linux/C:带有子进程的进程在添加waitid后都挂起

Ubuntu编译:C中的文件格式无法识别错误

多行表达式:C 编译器如何处理换行符?