I'm programming with SDL2, but I cannot grasp the reason behind the following. This works:
SDL_Window *window;
SDL_Surface *screen_surface;
SDL_Surface *picture;
auto initWindow(void)
{…}
auto loadMedia(void)
{…}
auto close(void)
{…}
int main(void)
{
initWindow();
loadMedia();
…
close();
}
However this does not:
auto initWindow(SDL_Window *window, SDL_Surface *screen_surface)
{…}
auto loadMedia(SDL_Surface *picture, std::string resource)
{…}
auto close(SDL_Window *window, SDL_Surface *picture)
{…}
int main(void)
{
SDL_Window *window;
SDL_Surface *screen_surface;
SDL_Surface *picture;
initWindow(window, screen_surface);
loadMedia(picture, "resource_file.bmp");
…
close(window, picture);
}
The only difference is that I take window
, screen_surface
and picture
out of file scope and put it into block scope (i.e. the main function), and instead of referencing global variables inside these functions, I use parameters.
However when I try to run this, it displays a white screen, but doesn't display any errors. I don't understand what goes wrong here.
Disclaimer : I have never done any SDL programming, so this is just an answer based on common sense and what I could read from the comments.
Say your initWindow
function sets some value to the window
variable. When that variable is declared in a global scope, modifications to it are also seen by all the other functions that use this variable.
This changes drastically when you change that variable to be a function parameter. Basing on the code you provided :
auto initWindow(SDL_Window *window, SDL_Surface *screen_surface)
{
window = SDL_GetWindow(); /* or something */
}
int main(void)
{
SDL_Window *window;
SDL_Surface *screen_surface;
initWindow(window, screen_surface);
/* some other code that uses 'window' */
}
Only the window
in initWindow
is actually set to the value of SDL_GetWindow
. The window
variable inside main
is not changed : all the other functions that need to use it in main
will be accessing an uninitialized variable, which is undefined behaviour. You also have a resource leak, since you're now never able to free what you got from SDL_GetWindow
. initWindow
actually receives a copy of window
, a one that's totally unrelated to the window
in main
.
Seeing how you're using C++, the best way around this is to have initWindow
accept a reference to the window
variable, like this :
auto initWindow(SDL_Window *&window, SDL_Surface *&screen_surface)
{
window = SDL_GetWindow(); /* or something */
}
int main(void)
{
SDL_Window *window;
SDL_Surface *screen_surface;
initWindow(window, screen_surface);
/* some other code that uses 'window' */
}
Now, the window
variable inside main
will be updated with what initWindow
does with it, and later code that uses window
in main
will access the resource that was acquired via SDL_GetWindow
.
However, C++ allows you to manage resources in a more efficient way via the usage of constructors and destructors, a concept known as RAII (Resource Acquisition Is Initialization). Look for C++ wrappers around the SDL objects which will make your life much easier, and if you don't, spend a while to write your own, or make them work with std::unique_ptr
(or std::shared_ptr
if you know that you need it). You'll thank yourself for it later on.