【发布时间】:2012-11-01 13:03:30
【问题描述】:
这似乎只是一个 Windows 问题,但我的问题的本质实际上是 C++11(或 MS C++0x TR1)。这是关于传递std::function 对象及其生命周期。
我想要一个通用框架,用于通过 Windows PostMessage API 进行异步执行。这是环境迫使我退出当前消息处理并在消息队列中注册任务的时候。
框架使用指向静态函数的指针(在WPARAM)和指向上下文的指针(在LPARAM)工作正常,其中包含一个“this”指针以及其他上下文。
我想把它提升到一个新的水平,并使用绑定和函数结构。我在 Visual Studio 2010 上(即 std::function 存在,但 TR1)。
到目前为止,这就是我所拥有的:
我正在通过教科书注册WM_ASYNC_TASK,并且我的Windows 程序(我实际上正在使用WTL)运行良好。 PostMessage 工作正常,消息最终将通过wparam 和lparam 正确并按预期到达onAsyncTask。
const UINT WM_ASYNC_TASK = RegisterWindowMessage(L"Async-Task");
我有一个CPlugin,这是我要发送任务的地方。我有 CHiddenWindow 这是获取消息的 Window 实现。我希望onAsyncTask 将函数转发回CPlugin。 hwnd 是窗口句柄。
在CPlugin 我已经:
void CPlugin::ShowMessageBox( void* arg ) {
wchar_t* text = (wchar_t*)arg;
MessageBox( NULL, text, L"Title", MB_OK )
}
void CPlugin::Sender( ) {
std::function<void(void*)> f = std::bind( &CPlug::ShowMessagebox,
this,
std::placeholders::_1 );
PostMessage( hwnd, WM_ASYNC_TASK, (WPARAM)f, (LPARAM)"Hello!!" );
}
在 WM_ASYNC_TASK 消息处理程序的 CHiddenWindow 中,我已经:
void CHiddinWindow::onAsyncTask( WPARAM wparam, LPARAM lparam, /* more arguments */ )
{
std::function<void(void*)> f = (std::function<void(void*)>)wparam;
void* arg = lparam;
f( arg );
}
问题:
- 目前,当我尝试将 f 转换为 WPARAM 时,编译器会报错,在
PostMessage内(WPARAM基本上是很长的)。 - 我可以使用
f的地址:(WPARAM)&f。 - 这引发了关于 f 生命周期的另一个问题。如何保存?
- 当传递
&f(将f保持在Sender()之外 - 这不是我的愿望)时,我在尝试取消引用f时在onAsyncHandler中遇到访问冲突。 - 关于生命周期,我可以将f置于
std::shared_ptr的控制之下吗? - 没有真正的理由将参数传递给 wparam 中的函数(在我的例子中是文本)。我认为应该有一种方法可以让
std::function对象的文本部分,但语法失败。
正如我所说,我在可变参数模板之前使用 VS 2010。 Microsoft 有 C++0x 的 TR1 实现。我正在寻找一个不包含 boost 的解决方案,因为它现在对我不可用。
谢谢!
【问题讨论】:
标签: c++ visual-studio-2010 winapi visual-c++ c++11