我正在尝试编写一个工厂函数来创建闭包,用作gstreamer中的“pad回调”。我已经提供了一个精简的例子,它应该可以在安装了gstreamer机箱和gstreamer二进制文件/插件的情况下编译。
通过我的研究,我使用了“impl-trait”方法,而不是装箱,使工厂函数工作。不过,我想找出装箱方法,因为它在某些情况下似乎更合适。
这是我得到的最接近。通过使用“Box”取消标记为<code>Closure function的部分的注释,可以看出该问题
CtrlC或从stdin退出\n应该关闭程序。
extern crate gstreamer as gst;
use gst::prelude::*;
use std::io;
fn create_impl_probe_fn(
x: i32,
) -> impl Fn(&gst::Pad, &mut gst::PadProbeInfo) -> gst::PadProbeReturn + Send + Sync + 'static {
move |_, _| {
println!("Idle... {}", x);
gst::PadProbeReturn::Pass
}
}
fn create_boxed_probe_fn(
x: i32,
) -> Box<Fn(&gst::Pad, &mut gst::PadProbeInfo) -> gst::PadProbeReturn + Send + Sync + 'static> {
Box::new(move |_, _| {
println!("Idle... {}", x);
gst::PadProbeReturn::Pass
})
}
fn main() {
println!("Starting...");
//TODO Pass args to gst?
gst::init().unwrap();
//GStreamer
let parse_line = "videotestsrc ! autovideosink name=mysink";
let pipeline = gst::parse_launch(parse_line).unwrap();
let ret = pipeline.set_state(gst::State::Playing);
assert_ne!(ret, gst::StateChangeReturn::Failure);
//Inline closure
let mut x = 1;
pipeline
.clone()
.dynamic_cast::<gst::Bin>()
.unwrap()
.get_by_name("mysink")
.unwrap()
.get_static_pad("sink")
.unwrap()
.add_probe(gst::PadProbeType::BLOCK, move |_, _| {
println!("Idle... {}", x);
gst::PadProbeReturn::Pass
});
//Closure function using 'impl'
x = 20;
let impl_probe_fn = create_impl_probe_fn(x);
//TEMP Test
pipeline
.clone()
.dynamic_cast::<gst::Bin>()
.unwrap()
.get_by_name("mysink")
.unwrap()
.get_static_pad("sink")
.unwrap()
.add_probe(gst::PadProbeType::BLOCK, impl_probe_fn);
/*
//Closure function using 'Box<>'
x = 300;
let boxed_probe_fn = create_boxed_probe_fn(x);
//TEMP Test
pipeline
.clone()
.dynamic_cast::<gst::Bin>()
.unwrap()
.get_by_name("mysink")
.unwrap()
.get_static_pad("sink")
.unwrap()
.add_probe(gst::PadProbeType::BLOCK, *boxed_probe_fn);
*/
//Input Loop
loop {
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
match input.trim() {
"exit" => break,
"info" => {
let (state_change_return, cur_state, old_state) =
pipeline.get_state(gst::CLOCK_TIME_NONE);
println!(
"Pipeline Info: {:?} {:?} {:?}",
state_change_return, cur_state, old_state
);
}
"pause" => {
let _ = pipeline.set_state(gst::State::Paused);
println!("Pausing");
}
"resume" => {
let _ = pipeline.set_state(gst::State::Playing);
println!("Resuming");
}
_ => println!("Unrecognized command: '{}'", input.trim()),
}
println!("You've entered: {}", input.trim());
}
//Shutdown
let ret = pipeline.set_state(gst::State::Null);
assert_ne!(ret, gst::StateChangeReturn::Failure);
println!("Shutting down streamer");
}
我知道网络上和SO上存在几个类似的问题,但我似乎不知道如何将任何解决方案应用于此特定功能。我在标题中包含了“非平凡”和“gstreamer”来区分。
[编辑]对不起,这里有更多的信息...只是不想把水弄混或使问题复杂化...
我不能发布我尝试过的所有内容。这是超过10个小时的小更改/尝试和许多标签。我可以复制一些看起来很接近的尝试,或者我期望有效的尝试。
上面的Box尝试是我根据这里的信息认为它会起作用的方式:https://doc.rust-lang.org/1.4.0/book/closures.html
https://doc.rust-lang.org/book/second-edition/ch19-05-advanced-functions-and-closures.html(这个没有关闭任何堆栈值,因此没有“移动”。)
从工厂功能生锈关闭(更多的,让我觉得我有什么应该工作...)
箱
这是add_probe签名:https://sdroege.github.io/rustdoc/gstreamer/gstreamer/trait.PadExtManual.html#tymethod.add_probe
这是上面的错误(冒犯add_probe呼叫未注释):
error[E0277]: the trait bound `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync: std::marker::Sized` is not satisfied
--> src/main.rs:63:14
|
63 | .add_probe(gst::PadProbeType::BLOCK, *boxed_probe_fn);
| ^^^^^^^^^ `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync`
所以,我想由于在编译时不知道闭包的大小,我不能将其作为参数传递?
将解引用更改为位于“”上方的赋值行上。add_probe'给出了类似的错误:
error[E0277]: the trait bound `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync: std::marker::Sized` is not satisfied
--> src/main.rs:57:13
|
57 | let boxed_probe_fn = *create_boxed_probe_fn(x);
| ^^^^^^^^^^^^^^ `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync`
= note: all local variables must have a statically known size
error[E0277]: the trait bound `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync: std::marker::Sized` is not satisfied
--> src/main.rs:63:14
|
63 | .add_probe(gst::PadProbeType::BLOCK, boxed_probe_fn);
| ^^^^^^^^^ `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `for<'r, 's, 't0> std::ops::Fn(&'r gst::Pad, &'s mut gst::PadProbeInfo<'t0>) -> gst::PadProbeReturn + std::marker::Send + std::marker::Sync`
我理解基于堆栈的绑定需要编译时大小......所以这几乎感觉不可能做到,除非add_probe函数本身采用了盒装
更多的尝试。有几个地方,包括add_probe函数签名本身,使用了类型参数和“where”子句来指定Fn特征。
add_probe声明:https://github . com/SDR oege/gstreamer-RS/blob/db 3 Fe 694154 c 697 af daf 3 efb 6 EC 65332546942 E0/gstreamer/src/pad . RS
对于类型Fn,未实现使用“where”子句:Sized的后期重新编译
所以,让我们尝试一下,将create_boxed_probe_fn更改为:
fn create_boxed_probe_fn<F>(x: i32) -> Box<F>
where F: Fn(&gst::Pad, &mut gst::PadProbeInfo) -> gst::PadProbeReturn + Send + Sync + 'static {
Box::new(move |_, _| {
println!("Idle... {}", x);
gst::PadProbeReturn::Pass
})
}
错误:
error[E0308]: mismatched types
--> src/main.rs:15:18
|
15 | Box::new(move |_, _| {
| __________________^
16 | | println!("Idle... {}", x);
17 | |
18 | | gst::PadProbeReturn::Pass
19 | | })
| |_________^ expected type parameter, found closure
|
= note: expected type `F`
found type `[closure@src/main.rs:15:18: 19:10 x:_]`
这似乎是因为我们已经指定了上面的类型,但闭包当然是它自己的类型。尝试以下不起作用,因为它是一个特征,并且不能使用“as”强制转换:
fn create_boxed_probe_fn<F>(x: i32) -> Box<F>
where F: Fn(&gst::Pad, &mut gst::PadProbeInfo) -> gst::PadProbeReturn + Send + Sync + 'static {
Box::new(move |_, _| {
println!("Idle... {}", x);
gst::PadProbeReturn::Pass
} as F)
}
错误:
error[E0308]: mismatched types
--> src/main.rs:15:18
|
15 | Box::new(move |_, _| {
| __________________^
16 | | println!("Idle... {}", x);
17 | |
18 | | gst::PadProbeReturn::Pass
19 | | } as F)
| |______________^ expected type parameter, found closure
|
= note: expected type `F`
found type `[closure@src/main.rs:15:18: 19:15 x:_]`
error[E0605]: non-primitive cast: `gst::PadProbeReturn` as `F`
--> src/main.rs:15:30
|
15 | Box::new(move |_, _| {
| ______________________________^
16 | | println!("Idle... {}", x);
17 | |
18 | | gst::PadProbeReturn::Pass
19 | | } as F)
| |______________^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
它提到了“来自”特征。我没有研究过,因为暗示结束的特征似乎不对。我甚至不确定这是否可能?
我还尝试了他们似乎称之为类型归因的东西(而不是使用“:F”作为F“),但目前似乎不支持:https://github.com/rust-lang/rust/issues/23416
这个人也有同样的问题,但是他的解决方案似乎是不使用类型参数,而是指定Fn部分,而不使用where子句。(这是我最顶级的非工作尝试。)不完全确定,因为他没有发布他是如何修复它的。https://github.com/rust-lang/rust/issues/51154
给任何一个box版本添加impl关键字似乎都无济于事。像我在未装箱的“工作”版本中那样使用它的语法似乎是新的,我还没有找到关于它的很好的文档。以下是一些相关信息:https://github . com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait . MD
更多相关链接:
如何将闭合件存储在Rust中?
Rust函数的返回类型中的闭包
预期的trait core::ops::FnMut,找到类型参数
https://doc.rust-lang.org/std/boxed/trait.FnBox.html
<代码>框
.add_probe(gst::PadProbeType::BLOCK, boxed_probe_fn);
这个问题可以简化为一个令人惊讶的简洁示例:
fn call<F: Fn()>(f: F) {
f();
}
fn main() {
let g = || (); // closure that takes nothing and does nothing
let h = Box::new(|| ()) as Box<dyn Fn()>; // that but as a Fn() trait object
call(g); // works
call(h); // fails
}
问题的核心是框
无法在trait对象上按值调用自
的方法。这使得无法调用Box
有可能为<code>框实现<code>Fn()
正如有人在问题评论中建议的,您可以创建自己的包装器结构来包装闭包,并实现< code>Box的< code>Fn()
您可以创建自己的trait<code>ProbeFn</code>,这是为任何正确类型的闭包实现的,并为<code>框实现<code>Fn()
在某些情况下,您可以使用
call(&*h);
不同于<代码>框
问题内容: 我有一个javascript函数,该函数调用通用函数对服务器进行ajax调用。我需要从ajax调用的回调函数中检索结果(true / false),但是我得到的结果始终是’undefined’。 如果没有我的全部逻辑,泛型函数的超级简化版本将是: 调用它的函数将类似于: “结果”变量始终为“未定义”,并且对其进行调试,我可以看到正在执行回调函数的“返回真”行。 为什么会这样?如何将返回
问题内容: 例如我有一个功能: 我怎样才能返回AJAX后得到的? 问题答案: 因为请求是异步的,所以您无法返回ajax请求的结果(而同步ajax请求是一个 糟糕的 主意)。 最好的选择是将自己的回调传递给f1 然后,您将像这样致电:
本文向大家介绍C# 装箱和拆箱的知识回顾,包括了C# 装箱和拆箱的知识回顾的使用技巧和注意事项,需要的朋友参考一下 装箱是将值类型转换为 object 类型或由此值类型实现的任何接口类型的一个过程。 当 CLR 对值类型进行装箱时,会将该值包装到 System.Object 内部,再将后者存储在托管堆上。 拆箱将从对象中提取值类型。 装箱是隐式的;拆箱是显式的。 装箱和拆箱的概念是类型系统 C#
问题内容: 我正在使用Postgresql 8.3,并具有以下简单功能,该功能会将a返回 给客户端 现在,我可以使用以下SQL命令来调用此函数并操纵返回的游标,但是游标名称是由PostgreSQL自动生成的 此外,如38.7.3.5中所述,显式地将游标名称声明为函数的输入参数 。返回游标。我可以声明自己的游标名称并使用此游标名称来操纵返回的游标,而不是为我自动生成的Postgresql吗?如果不是
在程序 function_return.go 中我们将会看到函数 Add2 和 Adder 均会返回签名为 func(b int) int 的函数: func Add2() (func(b int) int) func Adder(a int) (func(b int) int) 函数 Add2 不接受任何参数,但函数 Adder 接受一个 int 类型的整数作为参数。 我们也可以将 Adder
闭包作为参数(Taking closures as arguments) 现在我们知道了闭包是 trait,我们已经知道了如何接受和返回闭包;就像任何其它的 trait! 这也意味着我们也可以选择静态或动态分发。首先,让我们写一个获取可调用结构的函数,调用它,然后返回结果: fn call_with_one<F>(some_closure: F) -> i32 where F : Fn(i