我试图用C编写的库来制作某种ffi,但是卡住了。 这是一个测试用例:

extern crate libc;
use libc::{c_void, size_t};

// this is C library api call
unsafe fn some_external_proc(_handler: *mut c_void, value: *const c_void,
                             value_len: size_t) {
    println!("received: {:?}" , std::slice::from_raw_buf(
             &(value as *const u8), value_len as usize));
}

// this is Rust wrapper for C library api
pub trait MemoryArea {
    fn get_memory_area(&self) -> (*const u8, usize);
}

impl MemoryArea for u64 {
    fn get_memory_area(&self) -> (*const u8, usize) {
        (unsafe { std::mem::transmute(self) }, std::mem::size_of_val(self))
    }
}

impl <'a> MemoryArea for &'a str {
    fn get_memory_area(&self) -> (*const u8, usize) {
        let bytes = self.as_bytes();
        (bytes.as_ptr(), bytes.len())
    }
}

#[allow(missing_copy_implementations)]
pub struct Handler<T> {
    obj: *mut c_void,
}

impl <T> Handler<T> {
    pub fn new() -> Handler<T> { Handler{obj: std::ptr::null_mut(),} }

    pub fn invoke_external_proc(&mut self, value: T) where T: MemoryArea {
        let (area, area_len) = value.get_memory_area();
        unsafe {
            some_external_proc(self.obj, area as *const c_void,
                               area_len as size_t)
        };
    }
}

// this is Rust wrapper user code
fn main() {
    let mut handler_u64 = Handler::new();
    let mut handler_str = Handler::new();

    handler_u64.invoke_external_proc(1u64); // OK
    handler_str.invoke_external_proc("Hello"); // also OK
    loop  {
        match std::io::stdin().read_line() {
            Ok(line) => {
                let key =
                    line.trim_right_matches(|&: c: char| c.is_whitespace());

                //// error: `line` does not live long enough
                // handler_str.invoke_external_proc(key)
            }
            Err(std::io::IoError { kind: std::io::EndOfFile, .. }) => break ,
            Err(error) => panic!("io error: {}" , error),
        }
    }
}

防锈围栏

如果我在循环中取消注释行,我会得到“行不够长”的错误。 事实上,我意识到Rust害怕我可以将短生命引用存储在Handler对象内部的某个切片中,但我确信我不会,而且我也知道,将指针传递给外部是安全的proc(实际上,内存在C库端被临时复制)。

我有什么方法可以绕过这张支票吗?

#1楼 票数:3 已采纳

问题是,如果您真的想要为函数执行此操作,则会错误地对结构进行参数化。 在创建当前的Handler ,struct将专门使用包含生命周期的类型。 然而,寿命line是仅针对块,所以不可能有寿命为处理程序 ,持续多个循环迭代。

你想要的是生命与函数调用有关,而不是结构的生命。 如您所述,如果您将生命周期放在结构上,那么结构就能够存储该长度的引用。 你不需要它,所以把泛型类型放在函数上:

impl Handler {
    pub fn new() -> Handler { Handler{obj: std::ptr::null_mut(),} }

    pub fn invoke_external_proc<T>(&mut self, value: T) where T: MemoryArea {
        let (area, area_len) = value.get_memory_area();
        unsafe {
            some_external_proc(self.obj, area as *const c_void,
                               area_len as size_t)
        };
    }
}

修改后的答案

既然你想在类型上专门化结构,但是不要过多关注类型的生命周期,那么试试这个:

#[allow(missing_copy_implementations)]
pub struct Handler<T: ?Sized> {
    obj: *mut c_void,
}

impl<T: ?Sized> Handler<T> {
    pub fn new() -> Handler<T> { Handler{ obj: std::ptr::null_mut() } }

    pub fn invoke_external_proc(&mut self, value: &T) where T: MemoryArea {
        let (area, area_len) = value.get_memory_area();
        unsafe {
            some_external_proc(self.obj, area as *const c_void,
                               area_len as size_t)
        };
    }
}

在这里,我们允许类型不合格 由于您无法将未大小的值作为参数传递,因此我们现在必须使用引用。 我们还必须改变impl

impl MemoryArea for str {
    fn get_memory_area(&self) -> (*const u8, usize) {
        let bytes = self.as_bytes();
        (bytes.as_ptr(), bytes.len())
    }
}

  ask by swizard translate from so

未解决问题?本站智能推荐:

1回复

Rust:“..寿命不够长”

这是代码(具有 Rust 初学者难度): 操场我不确定我是否明白出了什么问题(但肯定有问题)。 'a在这里是一个main()函数作用域, index和refcell一直存在,直到 main() 退出。 matcher接受的参考RefCell是生活至少'a和引用一个框,生活至少'a和点到TInd
1回复

为什么变量的寿命不够长?

考虑应该返回给定Path的文件扩展名的此函数。 pub fn get_extension<'a>(path: &'a Path) -> Option<&'a str> { let path_str = path.as_str().unwrap(
1回复

PathBuf的寿命不够长

我正在尝试在构建脚本中使用以下代码: 我收到以下错误: 我实际上是在保存自己变量中的每个值。 那么这怎么可能不会超过这个陈述呢? 我知道还有“into_os_string”,但为什么我的方法不起作用? 我真的想要了解整个一生的事情,但这很难。 也许有人可以快速浏览我的例子并告诉
1回复

标称值和借用值的寿命不够长错误

尝试使用nom并迭代我的结果,但我无法弄清楚为什么这个借来的价值没有足够长的时间。 仍然是 Rust 的新手,并且已经头撞了几个小时。 将不胜感激帮助!use anyhow;use nom::{ bytes::complete::{tag, take}, character::compl
1回复

原始变量的寿命不够长

这段代码中有一个错误: 错误消息: error[E0597]: `x` does not live long enough --> src/main.rs:2:57 |2 | let a: Vec<_> = (1..10).flat_map(|x| (1..x).
1回复

循环变量的寿命不够长

过去几天我一直在玩Rust,而我仍然在努力处理内存管理(数字)。 我写了一个简单的项目 ,从lexing /解析文本文件创建结构层次结构(“关键字”)。 关键字的定义如下: 这是我对这个C结构的等价物: 层次结构只是关键字的容器,定义如下: 在parse函数( 它是完整解析器
1回复

静态未来的寿命不够长

在玩 async/await 时,我偶然发现了这个终生难题。 我假设predicate接受一个引用/值并产生静态未来 - 它没有对其参数的引用并且不捕获任何值。 相反,我抱怨寿命太短。 为什么它会失败,生命周期'2哪里?use futures::future;use std::future::Fut
1回复

参考'静态的寿命不够长?

考虑下一个代码:fn get_ref<'a, R>(slice: &'a Vec<i32>, f: fn(&'a Vec<i32>) -> R) -> Rwhere R: 'a,{ f(slice)}fn main() {