rust - 创建一个容器结构包含两个字段,从一个引用到另一个
问题描述
情况有点混乱。我正在尝试使用odbc-api
从 odbc 数据源查询结果,并将函数包装到 ffi。
odbc-api 定义了以下结构,
struct Envirnoment {...}
struct Connection<'c> {...}
impl Envirnoment {
pub fn connect_with_connection_string(
&self,
connection_string: &str,
) -> Result<Connection<'_>, Error> {...}
}
对于我的情况,在 C 端,create_connection
调用以返回 rust 中定义的连接处理程序。
#[no_mangle]
pub unsafe extern "C" fn create_connection(c_str: *const c_char) -> *mut Connection<'static> {
let env = Environment::new().unwrap();
let conn = env.connect_with_connection_string(CStr::from_ptr(c_str).to_str().unwrap()).unwrap();
Box::into_raw(Box::new(conn))
}
编译器返回错误如下。
error[E0515]: cannot return value referencing local variable `env`
--> odbc-demo/src/main.rs:37:5
|
36 | let conn = env.connect_with_connection_string(CStr::from_ptr(c_str).to_str().unwrap()).unwrap();
| --- `env` is borrowed here
37 | Box::into_raw(Box::new(conn))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
Connection 的生命周期无法解决,因为env
在函数返回时被丢弃。当处理程序暴露给 ffi 时,如何绑定env
并connection
进入单个结构?是std::pin
解决方案吗?如何在处理程序结构中定义连接的生命周期?
此外,我想制作env
一个全局静态 Arc 对象,以便我可以从单个 env 创建多个连接。
lazy_static!{
static ref ENV: Arc<Envirnoment> = Arc::new(Envirnoment::new().unwrap());
}
那么如何定义handler struct呢?
我预期的处理程序看起来像
#[repr(C)]
struct ConnectionHandler{
env: Arc<Envirnoment>,
conn: Connection<'_>,
}
更新:
我期望的处理程序是在堆栈上捕获生命周期有界对象和有界对象,以延长整个生命周期并将所有权转移给 ffi。我认为std::pin
应该按预期工作,因为预期的处理程序像异步函数一样工作。
在重新考虑了我的 FFI 实现的整个设计之后,我的设计结果是连接对象保持在(绿色)线程中,并用于std::sync::mpsc
将控制权转移给 ffi。
解决方案
推荐阅读
- python - 通过 for 循环定义 lambda 的 python 字典
- html - 在迭代中使用 div 元素的 onclick 事件获取数据
- maven - 在 .gitlab-ci.yml 中设置一个从 pom 读取 artifactId 名称的变量
- excel - 运行 Open 语句 (I/O) 以检查 .pdf 文件是否打开时,错误 70 权限被拒绝
- java - Maven 包在没有 web.xml 的情况下仍然失败,即使有
错误的 - html - 元素左侧的边距文本如何?
- php - PHP 或 PHPUnit 或 Laravel 是否具有递归数组比较的功能?
- android - 连接/断开电源时保持屏幕关闭
- performance - 着色器的 for 循环中的条件中断性能
- r - 如何在R中制作海盗情节