- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
背景:我试图避免使用 Mutex
/RefCell
/Option
在嵌入式系统的中断处理程序中跳舞。我不想使用堆(而且我不认为它应该是必要的——但随时告诉我错误)。我不能使用 std
.我看过 cortex-m-rtfm
它很整洁,但很有侵略性。无论如何,这是一种学习练习。如果可行,我更愿意使用闭包来处理中断,因为它感觉更接近于裸露的 Rust。我是一个彻头彻尾的 Rust 新手——我已经使用它大约一个星期了。在阅读文档、重读 Rust 书籍、博客文章等时,我尝试了很多不同的变体。我不知道我在这里做错了什么。
这是示例代码。要遵循的问题:
use core::cell::UnsafeCell;
pub struct Handler<'a> {
h: UnsafeCell<&'a dyn FnMut()>,
}
impl<'a> Handler<'a> {
pub fn new<T: FnMut()>(closure: &'a dyn FnMut()) -> Self {
Handler {
h: UnsafeCell::new(closure),
}
}
pub fn call(&self) {
unsafe {
// NOTE: type returned by `self.h.get()` is
// `*mut &'a (dyn std::ops::FnMut() + 'a)`
let h: *mut FnMut() = self.h.get();
h();
}
}
}
unsafe impl<'a> Sync for Handler<'a> {}
fn default_handler() {}
static HANDLER: Handler = Handler {
h: UnsafeCell::new(&default_handler),
};
#[test]
fn call_handler() {
let mut a: u32 = 0;
let foo = move || a += 1;
let mut handler = Handler::new(&foo);
handler.call();
a += 2; // Shouldn't this cause compilation failure because `a`
// was moved into the closure above?
assert_eq!(a, 1);
}
错误
error[E0618]: expected function, found `*mut dyn std::ops::FnMut()`
--> src/lib.rs:19:13
|
18 | let h: *mut FnMut() = self.h.get();
| - `*mut dyn std::ops::FnMut()` defined here
19 | h();
| ^--
| |
| call expression requires function
error[E0277]: expected a `std::ops::Fn<()>` closure, found `(dyn std::ops::FnMut() + 'a)`
--> src/lib.rs:18:35
|
18 | let h: *mut FnMut() = self.h.get();
| ^^^^^^^^^^^^ expected an `Fn<()>` closure, found `(dyn std::ops::FnMut() + 'a)`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `(dyn std::ops::FnMut() + 'a)`
= note: wrap the `(dyn std::ops::FnMut() + 'a)` in a closure with no arguments: `|| { /* code */ }
= note: required because of the requirements on the impl of `std::ops::FnMut<()>` for `&'a (dyn std::ops::FnMut() + 'a)`
= note: required for the cast to the object type `dyn std::ops::FnMut()`
解释:希望我的意图很明显:我将为 HANDLER
设置闭包。在main
,在进入永不退出的繁忙循环之前。闭包将可变地借用中断处理程序运行所需的东西,防止它在其他上下文中使用。自 main
永远不会退出,其中的堆栈分配变量实际上是 'static
,因此在设置闭包后的任何时候引用它们都不会有问题。中断处理程序本身(未显示)将简单地调用闭包来完成它的工作。要在静态中解决闭包(不是 Sized
)的存储问题,我需要存储对闭包的引用。 UnsafeCell
不一定是必需的,但因为我正在使用 FnMut()
它的引用对象需要是可变的,这会遇到 statics require immutable values
尝试设置 default_handler
时在创建 static mut HANDLER
的过程中.
问题:
正如发布的那样,此代码无法编译。由于某种原因,作业 let h: *mut FnMut() = self.h.get()
告诉我它
.好吧,我知道为什么它会找到那种类型。但为什么它期待
expected an Fn<()> closure, found (dyn std::ops::FnMut() + 'a)Fn<()>
?
在call_handler
测试,为什么要编译? foo
关闭move
这是它捕获的变量 a
.在闭包定义之后如何改变它?当我使用未实现 Copy
的类型尝试此代码时,它按预期失败了,但坦率地说,我很惊讶特质很重要。 foo
不是重点吗?拥有a
现在?
我意识到更改 HANDLER.h
存在潜在问题在代码中的任意点,但我会担心在有可行的概念验证之后解决这些问题。
最佳答案
我找到了一种方法来做我想做的事。它对于一般用途来说是非常不安全的,必须研究隐藏其缺乏安全性的适当机制,甚至可能是不可能的。主要技巧是使用 as
转换将可变特征对象转换为动态对象,并使用 core::mem::transmute
将其生命周期更改为 静态
。这是代码:
use core::cell::UnsafeCell;
use core::mem::transmute;
struct Handler {
h: UnsafeCell<*const dyn FnMut()>,
}
impl Handler {
unsafe fn replace(&self, f: &dyn FnMut()) {
let f_static: &'static dyn FnMut() = transmute(f);
*self.h.get() = f_static;
}
unsafe fn call(&self) {
let f: &mut dyn FnMut() = &mut *(*self.h.get() as *mut dyn FnMut());
f();
}
}
unsafe impl Sync for Handler {}
fn default_handler() {}
static HANDLER: Handler = Handler {
h: UnsafeCell::new(&default_handler),
};
fn main() {
let mut x: u32 = 0;
let closure = || x += 2;
unsafe {
HANDLER.replace(&closure);
HANDLER.call();
};
println!("x: {}", x); // Prints 2
}
Handler.h
包裹的闭包位于 UnsafeCell
中,以便于在运行时(在且仅在主循环内部)替换它。
关于rust - 在静态函数中使用 FnMut() 闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55818993/
给定一个 Rc ,在迭代器上映射时如何使用它?例如: use std::rc::Rc; fn main() { let f = Rc::new(|x| x); let v = vec!
use std::cell::RefCell; use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; fn
我有第三方库,代码如下: pub struct Foo { t: T } impl Foo where T: 'a + FnMut() -> &'a [u8] { pub fn from_ca
我正在尝试拥有一组可以采用 CharPredicate 的函数这是我自己的特征,通过 FnMut(char) -> bool 实现, Range , char等 目标是能够像这样调用助手: scan_
我有以下代码: struct Callable { callable: Box, } struct Parameters { text: &'a str, } struct Conte
这是一个可以组合Fn 闭包的compose 函数: fn compose(f: F1, g: F2) -> Box T3 + 'a> where F1: Fn(T1) -> T2 + 'a,
我正在为 Rust 编写一个 Phoenix 客户端库,利用来自 rust-websockets 的异步 websocket 客户端.现在我无法弄清楚如何将回调函数传递到处理 websocket 流量
pub fn create_future( notificator: mpsc::Sender, proxy: Proxy, ) -> impl Future { proxy.
背景:我试图避免使用 Mutex/RefCell/Option在嵌入式系统的中断处理程序中跳舞。我不想使用堆(而且我不认为它应该是必要的——但随时告诉我错误)。我不能使用 std .我看过 corte
如何在需要 FnMut 类型的上下文中使用盒装闭包,例如 pub fn main() { for n in (0..10).map(Box::new(|i| i * 2)) { print
我有一个类似这样的struct: struct Foo { callbacks: Vec, } 我想调用每个回调,但我的尝试不起作用: fn foo(&mut self) { for
这是来自 Rust by Example 的示例: pub trait Iterator { // The type being iterated over. type Item;
我正在尝试返回一个以 &Any 作为参数的闭包。以下代码返回编译器错误。 trait Selector { fn id(&self) -> i64; fn selector(&self
我想使用 FnMut(&[f32]) -> f32,为了不复制/粘贴完整签名,我想引入某种别名,但是 type Boo = FnMut(&[f32]) -> f32; fn f(mut f: F) {
自从 Iter's "all" fn takes type FnMut是否可以在检查条件和短路时更新元素?虽然我知道它不应该这样做,但是是什么阻止它更新值? fn main() { let a
我有以下代码片段,它实现了某种发射器结构: type Callback = Option; struct Emitter { cb: Callback } impl Emitter { fn
我已经通用实现了callback_list_stream,但是我似乎无法以专门的方式使用它。如果我按照T复制/粘贴代码,则该代码有效。 use futures::channel::mpsc::Rece
我有一个函数,collect_n ,返回 Future反复polls一个 futures::sync::mpsc::Receiver并将结果收集到一个向量中,并使用该向量进行解析。问题是它消耗了 Re
我正在尝试创建一个简单的程序,其中包含一个包含逐渐清空自身的集合的闭包: fn main() { let vector = vec![1, 2, 3]; let mut allow_o
基本上,我想编写一个返回闭包的函数。我怎样才能做到这一点而不必返回 Box ? 来自closures chapter of the rust book ,我读到闭包只是结构的语法糖和 FnOnce 的
我是一名优秀的程序员,十分优秀!