- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
c_strange_t
是一种不透明的 C 类型,只能在指针后面看到。包装此类型时,有时我们有责任使用 c_free_strange_t(*c_strange_t)
释放内存,而其他时候我们不负责释放数据,我们只负责准确控制生命周期。
如果这种类型可以映射到 Rust 中的 2 种类型,这两种类型的工作方式与 str
类似,那将是符合人体工程学的。和 String
, 哪里有 impl Deref<Target=str> for String
.借用的类型需要标记为仅在引用后有效。
这可能吗,如何实现?
最佳答案
这似乎可行,但它确实需要使用一个小的 unsafe
block ,因此您应该在 Miri 和 Valgrind 等常规工具下进行测试。这里做的主要假设1是c_void
不能正常构造。 #[repr(transparent)]
用于确保 FooBorrowed
新类型与 c_void
具有相同的内存布局。一切都应该以“只是一个指针”结束:
use std::{ffi::c_void, mem, ops::Deref};
#[repr(transparent)]
struct FooBorrowed(c_void);
struct FooOwned(*mut c_void);
fn fake_foo_new(v: u8) -> *mut c_void {
println!("C new called");
Box::into_raw(Box::new(v)) as *mut c_void
}
fn fake_foo_free(p: *mut c_void) {
println!("C free called");
let p = p as *mut u8;
if !p.is_null() {
unsafe { Box::from_raw(p) };
}
}
fn fake_foo_value(p: *const c_void) -> u8 {
println!("C value called");
let p = p as *const u8;
unsafe {
p.as_ref().map_or(255, |p| *p)
}
}
impl FooBorrowed {
fn value(&self) -> u8 {
fake_foo_value(&self.0)
}
}
impl FooOwned {
fn new(v: u8) -> FooOwned {
FooOwned(fake_foo_new(v))
}
}
impl Deref for FooOwned {
type Target = FooBorrowed;
fn deref(&self) -> &Self::Target {
unsafe { mem::transmute(self.0) }
}
}
impl Drop for FooOwned {
fn drop(&mut self) {
fake_foo_free(self.0)
}
}
fn use_it(foo: &FooBorrowed) {
println!("{}", foo.value())
}
fn main() {
let f = FooOwned::new(42);
use_it(&f);
}
如果 C 库实际上给你一个指针,你需要做更多的不安全
:
fn fake_foo_borrowed() -> *const c_void {
println!("C borrow called");
static VALUE_OWNED_ELSEWHERE: u8 = 99;
&VALUE_OWNED_ELSEWHERE as *const u8 as *const c_void
}
impl FooBorrowed {
unsafe fn new<'a>(p: *const c_void) -> &'a FooBorrowed {
mem::transmute(p)
}
}
fn main() {
let f2 = unsafe { FooBorrowed::new(fake_foo_borrowed()) };
use_it(f2);
}
正如您所指出的,FooBorrowed::new
返回一个生命周期不受限制的引用;这很危险。在许多情况下,您可以构造一个较小的作用域并使用提供生命周期的东西:
impl FooBorrowed {
unsafe fn new<'a>(p: &'a *const c_void) -> &'a FooBorrowed {
mem::transmute(*p)
}
}
fn main() {
let p = fake_foo_borrowed();
let f2 = unsafe { FooBorrowed::new(&p) };
use_it(f2);
}
这可以防止您在指针变量有效时使用引用,这不保证是真正的生命周期,但在许多情况下“足够接近”。太短不要太长更重要!
1 — 在 Rust 的 future 版本中,您应该使用外部类型来创建有保证的不透明类型:
extern "C" {
type my_opaque_t;
}
关于rust - 如何处理可以拥有或借用的 FFI 未确定大小的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42613798/
我正在使用 tcod-rs。用于绘制到 RootConsole 的每个方法都采用一个可变引用。中央循环是一个 while 循环,它等待窗口关闭、清除屏幕、绘制,然后刷新。 “检查窗口关闭”方法也采用可
This question already has answers here: How to return a reference to a sub-value of a value that is
我是新手,我已经阅读了有关所有权和借用的文档。显然,我开始为这个概念而苦苦挣扎... 这是我的代码: #[derive(Serialize, Deserialize, Debug)] pub stru
我在借阅检查器上遇到了问题。我有一个特征(Physics),它具有getters(例如velocity)和setters(例如velocity_mut)。它还具有使用getter和setter的默认方
我正在用 Rust 编写 Rogue-like。我有一个 Player,它有一个 Vec 的盒装 TimedEffects。定时效果有一个 activate(&mut Player) 和 deacti
我觉得 rc::Weak可以使用(某种)AsRef特征实现。我试图从弱指针借用一些共享内容,但这不会编译: use std::rc::Weak; struct Thing(Weak); impl Th
我正在学习Rust。对于我的第一个程序,我编写了以下代码来维护有关部分排序的数据: use std::collections::{HashMap, HashSet}; struct Node {
这个问题在这里已经有了答案: Cannot borrow as immutable because it is also borrowed as mutable in function argume
在尝试实现一个迭代器以产生对链表元素的可变引用时,我偶然发现了一个奇怪的问题。 这很好用: impl Iterator for LinkedListIterator{ fn next(&mut
我有this minimal example code : use std::borrow::BorrowMut; trait Foo {} struct Bar; impl Foo for Bar
struct State { x: i32 } trait A { fn a(&mut self, b: &i32); } impl A for State { fn a(&m
我有一个 Element 结构,它实现了一个更新方法,该方法需要一个滴答持续时间。该结构包含一个组件向量。允许这些组件在更新时修改元素。我在这里遇到借用错误,我不确定该怎么做。我尝试用 block 修
我正在尝试做这样的事情 use std::cell::{RefCell,Ref,RefMut}; use std::rc::Rc; struct Entity; struct Tile { e
我已连接到 Deribit websocket 以获取选项数据,但以下代码片段仅获得一个有效的数据响应,然后停止更新,但表示它仍在运行。 该网站建议使用 asyncio 模块,但能够使用以下代码片段提
我是一名优秀的程序员,十分优秀!