提问人:Rodrigo 提问时间:10/31/2023 最后编辑:Rodrigo 更新时间:10/31/2023 访问量:63
将 const std::function<void()> 作为 void* 作为 void* 中的参数传递SDL_AddTimer [closed]
Pass const std::function<void()> as parameter in SDL_AddTimer as void* [closed]
问:
我正在尝试将 a as 传递给 SDL_AddTimer,它的第三个参数是 .const std::function<void()> &
void *
void *
我试过reinterpret_cast
SDL_AddTimer(interval, wrapper, reinterpret_cast<void *>(const_cast<std::function<void()> *>(fn)));
但是在我的包装纸上,它崩溃了
uint32_t wrapper(uint32_t interval, void *param) {
auto fn = static_cast<std::function<void()> *>(param);
(*fn)(); // crashes here.
return interval;
}
我做错了什么?
编辑:用法:
timer t;
t.set(1000, []() {
std::cout << "Hello, world!" << std::endl;
});
答:
1赞
Remy Lebeau
10/31/2023
#1
你不能像你正在做的那样将引用转换为指针(你甚至不能像你正在做的那样将引用转换为指针)。std::function
void*
但是,您可以传递对象本身的地址。无论如何,这就是您的期望,例如:std::function
wrapper
auto &fn_ref = const_cast<std::function<void()> &>(fn); // note & not *
SDL_AddTimer(interval, wrapper, &fn_ref);
uint32_t wrapper(uint32_t interval, void *param) {
auto fn = static_cast<std::function<void()> *>(param);
(*fn)();
return interval;
}
只需确保对象在 SDL 计时器运行时保持活动状态即可。但是,根据您的使用示例,该对象似乎可能在计时器有机会调用它之前就超出了范围。因此,您必须将对象保存在某个地方,直到计时器停止运行,例如:std::function
std::function
std::function
class timer {
SDL_TimerID timerID = 0;
std::function<void()> timerFunc;
public:
timer() = default;
~timer();
void set(uint32_t interval, const std::function<void()> &fn);
void stop();
};
uint32_t wrapper(uint32_t interval, void *param) {
auto fn = static_cast<std::function<void()> *>(param);
(*fn)();
return interval;
}
timer::~timer() {
stop();
}
void timer::set(uint32_t interval, const std::function<void()> &fn) {
stop();
timerFunc = fn;
timerID = SDL_AddTimer(interval, wrapper, &timerFunc);
}
void timer::stop() {
if (timerID != 0) {
SDL_RemoveTimer(timerID);
timerID = 0;
}
}
评论
0赞
Rodrigo
10/31/2023
它完美无缺,谢谢。一个问题,我可以传递 fn 作为参考还是应该传递副本?
1赞
Remy Lebeau
10/31/2023
@Rodrigo您必须传递一份副本,因为原件是临时的。我已经更新了我的示例来展示这一点。fn
上一个:我想在 C SDL 中放大图像
评论
const std::function<void()> &
fn
const_cast<std::function<void()> *>(fn)
fn