Putting SDL into a class (no image is being displayed)

Hi.
Currently, I have my SDL project in one file (Source.cpp).
It works fine, its main purpose is to display an image from my hard disk onto the screen, then quit after a few seconds.

SOURCE.CPP

#include "SDL.h"
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//The window we'll be rendering to
SDL_Window* gWindow = NULL;

//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;

//The image we will load and show on the screen
SDL_Surface* gHelloWorld = NULL;

bool init()
{
	//Initialization flag
	bool success = true;

	//Initialize SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
		success = false;
	}
	else
	{
		//Create window
		gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
		if (gWindow == NULL)
		{
			printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
			success = false;
		}
		else
		{
			//Get window surface
			gScreenSurface = SDL_GetWindowSurface(gWindow);
		}
	}

	return success;
}

bool loadMedia()
{
	//Loading success flag
	bool success = true;

	//Load splash image
	gHelloWorld = SDL_LoadBMP("shaan.bmp");
	if (gHelloWorld == NULL)
	{
		printf("Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError());
		success = false;
	}

	return success;
}

void close()
{
	//Deallocate surface
	SDL_FreeSurface(gHelloWorld);
	gHelloWorld = NULL;

	//Destroy window
	SDL_DestroyWindow(gWindow);
	gWindow = NULL;

	//Quit SDL subsystems
	SDL_Quit();
}

int main(int argc, char* args[])
{
	//Start up SDL and create window
	if (!init())
	{
		printf("Failed to initialize!\n");
	}
	else
	{
		//Load media
		if (!loadMedia())
		{
			printf("Failed to load media!\n");
		}
		else
		{
			//Apply the image
			SDL_BlitSurface(gHelloWorld, NULL, gScreenSurface, NULL);

			//Update the surface
			SDL_UpdateWindowSurface(gWindow);

			//Wait two seconds
			SDL_Delay(2000);
		}
	}

	//Free resources and close SDL
	close();

	return 0;
}

Here is the version where I have made a “mySDL” class

  • SDLManager.h
  • SDLManager.cpp
  • Source2.cpp

These three files are meant to do exactly the same thing as Source2.cpp, No image is displayed and no error is given. I believe it has something to do with my usage of pointers/passing pointers to functions/referencing memory addresses.
Can someone help me?
Here is the source code for the 3 files:

SDLMANAGER.CPP
#include “SDLManager.h”

SDLManager::SDLManager()
{
}


SDLManager::~SDLManager()
{
}


bool SDLManager::init(SDL_Window *myWindow, SDL_Surface *mySurface)
{

	bool success = true;

	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialise! SDL_Error: %s\n", SDL_GetError());
		success = false;
	}


	else
	{
		myWindow = SDL_CreateWindow("SDL-Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);



		if (myWindow == NULL)
		{

			printf("Window could not be created! SDL-Error: %s\n", SDL_GetError());
			success = false;

		}

		else
		{
			mySurface = SDL_GetWindowSurface(myWindow);


		}

	}

	return success;
}

bool SDLManager::loadMedia( SDL_Surface *myImage)
{
	bool success = true;

	myImage = SDL_LoadBMP("shaan.bmp");

	if (myImage == NULL)
	{

		printf("Unable to load image %s! SDL Error: %s\n,", "shaan.bmp", SDL_GetError());
		success = false;
	}

	return success;
}

void SDLManager::close(SDL_Window *myWindow, SDL_Surface *myImage)
{
	SDL_FreeSurface(myImage);
	myImage = NULL;

	SDL_DestroyWindow(myWindow);
	myWindow = NULL;

	SDL_Quit();
}

SDLMANAGER.H
#pragma once
#include “SDL.h”
#include <stdio.h> //standard io

class SDLManager
{
public:

	//Screen dimension constants
	const int SCREEN_WIDTH = 640;
	const int SCREEN_HEIGHT = 480;

	SDLManager();
	~SDLManager();


	bool init(SDL_Window *myWindow, SDL_Surface *mySurface);
	bool loadMedia(SDL_Surface *myImage);
	void close(SDL_Window *myWindow, SDL_Surface *myImage);

};

SOURCE2.CPP

#include "SDLManager.h"

int main(int argc, char* args[])
{


	SDLManager *mySDL = new SDLManager();


	SDL_Window *myWindow = NULL;
	SDL_Surface *mySurface = NULL;
	SDL_Surface *myImage = NULL;


	if (!mySDL->init(myWindow, mySurface))
	{
		printf("Failed to initialise!");
			//return 0; No need, as return is done in init function.
	}

	else {
		if (!mySDL->loadMedia(myImage))
		{

			printf("Failed to load media.");
		}
		else 
		{

			SDL_BlitSurface(myImage, NULL, mySurface, NULL);

			SDL_UpdateWindowSurface(myWindow);

			SDL_Delay(5000);

		}

	}

	mySDL->close(myWindow, myImage);
	
	return 0;
}

Yes, your code stores the pointers of the window, surface, and image only in the variables that stay in the scope of the init and loading functions. It will never reach the blit and update functions.

If you write a function that takes a pointer like this:

void func(char * arg1)
{
    arg1 = NULL;
}

int main(int argc, char * argv[])
{
    char * var = argv[0];
    func(var);
    return 0;
}

The arg1 variable stays in the scope of the function and gets initialized with the value of var. As soon as the function returns, this variable is discarded, including its value. var will never see any changes this way.

In C, you would use a pointer to a pointer to pass the memory location of the var variable which lets the function change the value:

void func(char ** arg1)
{
    *arg1 = NULL;
}

int main(int argc, char * argv[])
{
    char * var = argv[0];
    func(&var);
    return 0;
}

Now, var is actually NULL after the function returns. You could apply this to your code and get it working.

You are free to design your application this way, but it really is just C and it would be a shame to ignore passing-by-reference or the useful or features of classes in C++.

An example that does the same thing in C++:

class Pointers {
public:
    char * var;

    Pointers(char * arg1);

    void func();
};

Pointers::Pointers(char * arg1)
: var(arg1)
{
}

void Pointers::func()
{
    var = NULL;
}

int main(int argc, char * argv[])
{
    Pointers p1(argv[0]);
    p1.func();
    return 0;
}

The class functions get access to the members and a lot of pointer passing can be avoided.

1 Like

I have tried passing by a double pointer, then using the “address of” symbol when making a function call. But this time the screen is black instead of white - although the image is STILL not loading :open_mouth:

Sounds like you got the window surface working, but not the loading of the image.

Here’s the modified version of your code that I tested:

source.cpp
#include "SDL.h"
#include <stdio.h> //standard io

class SDLManager
{
public:
	//Screen dimension constants
	const int SCREEN_WIDTH = 640;
	const int SCREEN_HEIGHT = 480;

	SDLManager();
	~SDLManager();

	bool init(SDL_Window **myWindow, SDL_Surface **mySurface);
	bool loadMedia(SDL_Surface **myImage);
	void close(SDL_Window *myWindow, SDL_Surface *myImage);
};

SDLManager::SDLManager()
{
}

SDLManager::~SDLManager()
{
}

bool SDLManager::init(SDL_Window **myWindow, SDL_Surface **mySurface)
{
	bool success = true;

	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialise! SDL_Error: %s\n", SDL_GetError());
		success = false;
	}
	else
	{
		*myWindow = SDL_CreateWindow("SDL-Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);

		if (*myWindow == NULL)
		{
			printf("Window could not be created! SDL-Error: %s\n", SDL_GetError());
			success = false;
		}
		else
		{
			*mySurface = SDL_GetWindowSurface(*myWindow);
		}
	}

	return success;
}

bool SDLManager::loadMedia( SDL_Surface **myImage)
{
	bool success = true;

	*myImage = SDL_LoadBMP("shaan.bmp");

	if (*myImage == NULL)
	{
		printf("Unable to load image %s! SDL Error: %s\n,", "shaan.bmp", SDL_GetError());
		success = false;
	}

	return success;
}

void SDLManager::close(SDL_Window *myWindow, SDL_Surface *myImage)
{
	SDL_FreeSurface(myImage);
	myImage = NULL;

	SDL_DestroyWindow(myWindow);
	myWindow = NULL;

	SDL_Quit();
}

int main(int argc, char* args[])
{
	SDLManager *mySDL = new SDLManager();

	SDL_Window *myWindow = NULL;
	SDL_Surface *mySurface = NULL;
	SDL_Surface *myImage = NULL;

	if (!mySDL->init(&myWindow, &mySurface))
	{
		printf("Failed to initialise!\n");
		//return 0; No need, as return is done in init function.
	} else {
		if (!mySDL->loadMedia(&myImage))
		{
			printf("Failed to load media.\n");
		}
		else
		{
			for (int i = 0; i < 10; i++)
			{
				SDL_BlitSurface(myImage, NULL, mySurface, NULL);
				SDL_UpdateWindowSurface(myWindow);
				SDL_Delay(500);
			}
		}
	}

	mySDL->close(myWindow, myImage);

	return 0;
}
1 Like

I’ve read through it and it looks like my code is very similar.
I will read through it again though.

I confused one of the parameters with another in the “init” function.
(This is what I did, Im juut showing you the function declaration)

void initialisationCheck( SDL_Window **myWindow, SDL_Surface *mySurface, SDL_Surface **myImage);

and then I did this in the initialisationCheck function definition in the .cpp file):
*myImage= SDL_GetWindowSurface(*myWindow);

I assigned the address of the window that the double pointer “myWindow” points to, to the wrong double pointer (*myImage) when it should have been to (*mySurface)

This meant when I was blitting in
SDL_BlitSurface(p_mySSImage, NULL, p_mySDLScreenSurface, NULL);

I would have my image “shaan.bmp” blitting onto its own surface? Which would not have worked as for an image to be blitted it needs a surface which contains the image (myImage) and a destination surface (mySurface). The image was loaded with the function SDL_LoadBMP and returned to the function argument.

Basically my problem was I think I made the wrong pointer point to something.
it is working now.

Thank you very much for the help.