[英]Should I try to access self in a PointerPressed event handler for a CoreApp in the Rust Crate for Windows?
E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。 E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。 E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。 E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement. E0759 self 有一个匿名生命周期 '_ 但它需要满足一个 '静态生命周期要求。
#![windows_subsystem = "windows"]
use windows::{
core::*,
Foundation::*,
ApplicationModel::Core::*,
Foundation::Numerics::*,
Foundation::TypedEventHandler,
Win32::System::Com::*,
UI::{
Core::*,
Composition::*,
},
};
use windows as Windows;
#[implement(Windows::ApplicationModel::Core::IFrameworkViewSource)]
struct App();
#[allow(non_snake_case)]
impl App {
fn CreateView(&self) -> Result<IFrameworkView> {
// TODO: need self query `self.into()` to support implementing both IFrameworkViewSource and IFrameworkView on the same object.
Ok(AppView::new().into())
}
}
#[implement(Windows::ApplicationModel::Core::IFrameworkView)]
struct AppView {
m_target: Option<CompositionTarget>,
m_visuals: Option<VisualCollection>,
m_selected: Option<Visual>,
m_offset: Option<Vector2>,
}
#[allow(non_snake_case)]
impl AppView {
fn new() -> Self {
Self {
m_target: None,
m_visuals: None,
m_selected: None,
m_offset: None,
}
}
fn Initialize(&self, _: &Option<CoreApplicationView>) -> Result<()> {
Ok(())
}
fn Load(&self, _: &HSTRING) -> Result<()> {
Ok(())
}
fn Uninitialize(&self) -> Result<()> {
Ok(())
}
fn Run(&self) -> Result<()> {
let window = CoreWindow::GetForCurrentThread()?;
window.Activate()?;
let dispatcher = window.Dispatcher()?;
dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit)?;
Ok(())
}
fn SetWindow(&mut self, window: &Option<CoreWindow>) -> Result<()> {
let compositor = Compositor::new()?;
let root = compositor.CreateContainerVisual()?;
self.m_target = Some(compositor.CreateTargetForCurrentView()?);
let target = self.m_target.as_ref().unwrap();
target.SetRoot(&root)?;
self.m_visuals = Some(root.Children()?);
let visuals = self.m_visuals.as_ref().unwrap(); // extra line for test is ok
window.as_ref().unwrap().PointerPressed(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args|
{
let args = args.as_ref().unwrap();
let currentpoint = args.CurrentPoint().unwrap();
let point = currentpoint.Position().unwrap(); // Point not Vector2
//let visuals: &VisualCollection = self.m_visuals.as_ref().unwrap();
let visuals = self.m_visuals.as_ref().unwrap(); // E0759 self has an anonymous lifetime '_ but it need to satisfy a 'static lifetime requirement
Ok(())
}
))?;
window.as_ref().unwrap().PointerMoved(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, _args|
{
Ok(())
}
))?;
window.as_ref().unwrap().PointerReleased(TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, _args|
{
Ok(())
}
))?;
Ok(())
}
fn AddVisual(_point: Point) {
//...
}
}
fn main() -> Result<()> {
unsafe {
CoInitializeEx(std::ptr::null_mut(), COINIT_MULTITHREADED)?;
}
let app: IFrameworkViewSource = App().into();
CoreApplication::Run(app)?;
Ok(())
}
Capturing AppView's instance self reference in v0.30 doesn't seem to be possible, because TypedEventHandler::new
has a + 'static
requirement for the callback ( see ), so any reference it captures must be 'static
(a global variable basically).在 v0.30 中捕获 AppView 的实例自引用似乎是不可能的,因为TypedEventHandler::new
对回调有+ 'static
要求( 请参阅),因此它捕获的任何引用都必须是'static
(基本上是全局变量) .
Please raise an issue here if you want this.如果你想要这个,请在这里提出一个问题。 Your code looks like a reasonable way to use this API.您的代码看起来是使用此 API 的合理方式。
Until then, as a workaround you could make a level of indirection, where instead of storing the state directly in AppView, you store it in a shared helper object, for example:在此之前,作为一种解决方法,您可以进行一定程度的间接操作,而不是将 state 直接存储在 AppView 中,而是将其存储在共享帮助程序 object 中,例如:
struct AppView {
m_state: Rc<RefCell<AppViewState>>,
}
struct AppViewState {
m_target: Option<CompositionTarget>,
m_visuals: Option<VisualCollection>,
m_selected: Option<Visual>,
m_offset: Option<Vector2>,
}
You can clone it move into the callback for modification:您可以将其克隆到回调中进行修改:
let pointer_pressed_state = Rc::clone(self.m_state);
let pointer_pressed_handler = TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args| {
let state_ref = pointer_pressed_state.borrow(); // or .borrow_mut()
...
});
let pointer_moved_state = Rc::clone(self.m_state);
let pointer_moved_handler = TypedEventHandler::<CoreWindow, PointerEventArgs>::new(move |_, args| {
let state_ref = pointer_moved_state.borrow(); // or .borrow_mut()
...
});
This should work, because now the closure doesn't capture any references (everything gets moved).这应该可行,因为现在闭包不会捕获任何引用(一切都被移动了)。
If you want, you can add methods to AppViewState, and call them from the closures like state_ref.OnPointerPressed(...)
.如果需要,您可以向 AppViewState 添加方法,并从state_ref.OnPointerPressed(...)
之类的闭包中调用它们。
Another option that I don't recommend is to use unsafe and cast self to 'static.我不推荐的另一个选择是使用 unsafe 并将 self 转换为 'static.
Rc<RefCell> gives a thread related compiler error but changing to Arc<Mutex> resolves this. Rc<RefCell> 给出线程相关的编译器错误,但更改为 Arc<Mutex> 可以解决此问题。
struct AppView {
m_state: Arc<Mutex<AppViewState>>,
}
struct AppViewState {
m_target: Option<CompositionTarget>,
m_visuals: Option<VisualCollection>,
m_selected: Option<Visual>,
m_offset: Option<Vector2>,
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.