简体   繁体   English

返回带有生命周期的FFI结构

[英]Return struct with lifetime for FFI

I am trying to expose a function from the woothee-rust crate to Ruby. 我正在尝试从woothee-rust板条箱向Ruby公开一个功能。 To do this, I am parsing an input string and attempting to return the result as a C struct. 为此,我正在解析输入字符串,并尝试将结果作为C结构返回。 I run into an issue where the lifetime of the parser "does not live long enough". 我遇到一个问题,即解析器的生存期“寿命不长”。 I am not sure why the parser's lifetime must live past the function. 我不确定为什么解析器的生命周期必须超过该函数。

#![feature(libc)]
#![feature(cstr_to_str)]
#![feature(cstr_memory)]
extern crate libc;
extern crate woothee;

use woothee::parser::{Parser,WootheeResult};
use std::ffi::{CStr,CString};

#[no_mangle]
pub extern fn parse<'a>(ua_string: *const libc::c_char) -> WootheeResult<'a> {
    let input = unsafe { CStr::from_ptr(ua_string) };
    let parser = Parser::new();
    parser.parse(input.to_str().unwrap()).unwrap()
}

Here is the error I get: 这是我得到的错误:

error: `parser` does not live long enough
  --> src/lib.rs:14:5
   |
14 |     parser.parse(input.to_str().unwrap()).unwrap()
   |     ^^^^^^ does not live long enough
15 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the body at 11:77...
  --> src/lib.rs:11:78
   |
11 |   pub extern fn parse<'a>(ua_string: *const libc::c_char) -> WootheeResult<'a> {
   |  ______________________________________________________________________________^ starting here...
12 | |     let input = unsafe { CStr::from_ptr(ua_string) };
13 | |     let parser = Parser::new();
14 | |     parser.parse(input.to_str().unwrap()).unwrap()
15 | | }
   | |_^ ...ending here

After expanding lifetime elision, the signature of Parser::parse is 扩展生存期选择后, Parser::parse的签名为

fn parse<'a, 'b>(&'a self, agent: &'b str) -> Option<WootheeResult<'a>>

In words, that is: 换句话说:

Given a reference to a Parser and a reference to a str , maybe return a WootheeResult that contains one or more references to the Parser or some component of it. 给定对Parser的引用和对str的引用,可能返回WootheeResult ,其中包含一个或多个对Parser或其某些组件的引用。

However, you immediately destroy the Parser when the function exits. 但是,当函数退出时,您会立即销毁Parser So, no, you cannot do this because to do so would allow accessing a reference to undefined memory. 因此,不,您不能执行此操作,因为这样做将允许访问对未定义内存的引用。 Rust has prevented you from introducing a security hole into your program. Rust阻止您在程序中引入安全漏洞。

Returning to the error message, hopefully it makes more sense now: 返回错误消息,希望现在更有意义:

  • " parser does not live long enough" parser寿命不足”
  • "borrowed value must be valid for the lifetime 'a" “借入的值必须在有效期内'a”有效

I haven't dug into the implementation of woothee, but this signature is pretty surprising. 我没有深入研究woothee的实现,但是这个签名非常令人惊讶。 I could understand if it returned references to the string that was parsed, but not to the parser . 我可以理解它是否返回对已解析的字符串的引用,而不是对解析器的引用。 This is especially surprising as the method takes &self — it's unlikely to be modifying the internals based on the parsing, so why would it return a reference to itself? 由于该方法需要&self这尤其令人惊讶-它不太可能基于解析来修改内部结构,所以为什么它返回对自身的引用?

Looking at the implementation of Parser::new , the lifetime appears to be driven from dataset::get_default_dataset : 看一下Parser::new的实现,生命周期似乎是由dataset::get_default_dataset驱动的:

pub fn get_default_dataset<'a>() -> HashMap<&'a str, WootheeResult<'a>>

As stated in Is there any way to return a reference to a variable created in a function? 如中所述, 有没有办法返回对在函数中创建的变量的引用? , you can't return a reference to a local variable unless that local variable is 'static . ,除非该局部变量为'static否则您不能返回对该局部变量的引用。 With the caveat that I haven't tried this, I'm 80% sure that the crate could be changed to return 'static strings from get_default_dataset , then parse would be 需要说明的是,我还没有尝试过,所以我80%可以确定可以将板条箱更改为从get_default_dataset返回'static字符串”,然后parse

impl<'a> Parser<'a> {
    fn parse<'b>(&'b self, agent: &'b str) -> Option<WootheeResult<'a>>
}

And the WootheeResult would be WootheeResult<'static> , and then things would "just work". 并且WootheeResult将是WootheeResult<'static> ,然后事情将“正常工作”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM