1

I'm in the process of wrapping SDL into C++ objects. Basically, I'm just tired of seeing SDL_ in my code. I'd like at least namespaces... SDL::Window. I've done that, its going more or less fine.

Issue arises with events. I'd like it to be event driven (callbacks) rather than me having to poll an events queue. (the propagation routines you have to write to get SDL_Event fit the abstraction I've designed is painful).

Take for example, a Window class. Its constructor calls

SDL_AddEventWatch(window_events, this);

where window_events is a static member of the Window class. It catches anything of type 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 class also contains hook and unhook methods. Each takes a std::function. This is what mWindowCallbacks is a collection of. Any external routine interested in an event gets a copy forwarded to it.

//...
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);
    }
}

Usage:

///...
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);

Close:

void Window::close()
{   
    SDL_DelEventWatch(window_events, this);
    SDL_DestroyWindow(mWindow);
    mWindowCallbacks.clear();       
}

To me, this doesn't seem like terrible design. Once you press close on the window the cbk_close is invoked, it calls close, it sets the quit flag... Then it returns to the window_events loop. As expected... However that function doesn't seem to return control to the program.

This is what I need help with. I don't really understand why. I think its hijacking the main thread, as the program will exit once that function exits if you have one window, or... crash if you have two.

Am I on the right lines with that? I've been stuck on this for a week. Its really rather infuriating. To anyone willing to have a play about with it; here's the git repo for the full code.
Windows, Visual Studio 2015/VC solution. https://bitbucket.org/andywm/sdl_oowrapper/

2
  • allegro 5 is event driven. Commented Mar 31, 2017 at 0:55
  • 1
    @sailfish009 - While I appreciate there may be alternatives to SDL. That wasn't the question I was asking. Thanks anyway though. Commented Mar 31, 2017 at 11:11

1 Answer 1

0

Okay, so I think I more or less understand what's going on here now.

SDL_AddEventWatch(void (*)(void *, SDL_Event*), void *) 

If you're using C++, you should set the calling convention.

SDLCALL

In my case;

int SDLCALL
Window::window_events(void* data, SDL::Events::Event* ev)

This seems to stop the sdl events system from nabbing the main thread.

As for why its crashing with multiple windows... Well, if I remove this line

SDL_DelEventWatch(window_events, this);

it doesn't crash... Not really sure why yet, but if I figure it out I'll amend my answer - and if anyone with more experienced with SDL could fill me in.. That'd be great.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.