我正在将SDL包装到C ++对象中。基本上,我只是厌倦了在我的代码中看到SDL_。我至少想要名称空间...... SDL :: Window。我已经做到了,它或多或少都好了。
问题出现在事件中。我希望它是事件驱动(回调)而不是我必须轮询事件队列。 (为了让SDL_Event符合我设计的抽象,你必须编写的传播例程很痛苦。)
以一个Window类为例。它的构造函数调用
SDL_AddEventWatch(window_events, this);
其中window_events是Window类的静态成员。它捕获任何类型的SDL_WINDOWEVENT。
int Window::window_events(void* data, SDL::Events::Event* ev)
{
if (ev->type == SDL::Events::Window::Any)
{
auto win = static_cast<Window *>(data);
if (ev->window.windowID == SDL_GetWindowID(win->mWindow))
{
std::vector<event_callback> callbacks = win->mWindowCallbacks;
for (const auto cbk : callbacks)
{
cbk(*ev);
}
}
}
return 0;
}
My Window类还包含hook和unhook方法。每个都采用std :: function。这就是mWindowCallbacks的集合。任何对事件感兴趣的外部例程都会将一个副本转发给它。
//...
using event_callback = std::function<void(SDL::Events::Event)>;
//...
template<typename T> bool
find_func(const T & object,
const std::vector<T> & list,
int * location=nullptr)
{
int offset = 0;
for (auto single : list)
{
if (single.target<T>() ==
object.target<T>())
{
if (location != nullptr) *location = offset;
return true;
}
offset++;
}
return false;
}
void
Window::hook(event_callback cbk)
{
if (!find_func(cbk, mWindowCallbacks))
{
mWindowCallbacks.push_back(cbk);
}
}
void
Window::unhook(event_callback cbk)
{
int offset = 0;
if (find_func(cbk, mWindowCallbacks, &offset))
{
mWindowCallbacks.erase(mWindowCallbacks.begin() + offset);
}
}
用法:
///...
void cbk_close(SDL::Events::Event e)
{
if (e.window.event == SDL::Events::Window::Close)
{
window.close();
quit = true;
}
}
///...
std::function<void(SDL::Events::Event)> handler = cbk_close;
SDL::Window window;
window.hook(handler);
关闭:
void Window::close()
{
SDL_DelEventWatch(window_events, this);
SDL_DestroyWindow(mWindow);
mWindowCallbacks.clear();
}
对我而言,这看起来并不像是糟糕的设计。 一旦你按下窗口上的关闭,调用cbk_close,它调用close,它设置退出标志......然后它返回到window_events循环。正如预期的那样......但是这个功能似乎并没有将控制权交还给程序。
这是我需要帮助的。我真的不明白为什么。我认为它劫持主线程,因为如果你有一个窗口,程序将退出该函数退出,或者如果你有两个窗口则崩溃...
我是否在正确的路线上?我已经坚持了一个星期。它真的很令人气愤。对任何愿意玩弄它的人;这里是完整代码的git repo Windows,Visual Studio 2015 / VC解决方案。 https://bitbucket.org/andywm/sdl_oowrapper/
答案 0 :(得分:0)
好的,所以我想我或多或少了解现在在这里发生了什么。
SDL_AddEventWatch(void (*)(void *, SDL_Event*), void *)
如果您正在使用C ++,则应设置调用约定。
SDLCALL
就我而言;
int SDLCALL
Window::window_events(void* data, SDL::Events::Event* ev)
这似乎阻止了sdl事件系统抓住主线程。
至于为什么它会崩溃多个窗口...好吧,如果我删除这一行
SDL_DelEventWatch(window_events, this);
它并没有崩溃......还不确定为什么会这样,但如果我弄明白我会修改我的答案 - 如果有更多SDL经验的人可以填补我的话......那&# 39;很棒。