"SDL_AddTimer" From Within A C++ Class?

“SDL_AddTimer” From Within A C++ Class???

Hi,

Is it possible to use “SDL_AddTimer” from within a C++ class?

Getting this error:

Code:
C:\Users\jezlee\Desktop\ChaosTimer\src\screens.cpp|21|error: argument of type ‘Uint32 (Screens::)(Uint32, void*)’ does not match ‘Uint32 ()(Uint32, void)’

Here is my relevant source code:

Code:
#include “SDL.h”
#include “SDL_image.h”
#include “SDL_mixer.h”
#include “SDL_ttf.h”
#include “SDL_opengl.h”

#include “screens.h”

#include “visuals.h”
#include “input.h”

extern Visuals* visuals;
extern Input* input;

//-------------------------------------------------------------------------------------------------
Screens::Screens(void)
{
ScreenIsDirty = true;
ScreenToDisplay = SixteenBitSoftScreen;

ScreenDisplayTimer = SDL_AddTimer(16, ProcessScreenToDisplay, NULL); //<--ERROR HERE!!!

}

//-------------------------------------------------------------------------------------------------
Screens::~Screens(void)
{
SDL_RemoveTimer(ScreenDisplayTimer);
}

//-------------------------------------------------------------------------------------------------
Uint32 Screens::ProcessScreenToDisplay(Uint32 interval, void *param)
{
input->GetAllUserInput();

switch(ScreenToDisplay)
{
    case SixteenBitSoftScreen:
        DisplaySixteenBitSoftScreen();
        break;


    default:
        break;
}

return(interval);

}

//-------------------------------------------------------------------------------------------------
void Screens::DisplaySixteenBitSoftScreen(void)
{
if (ScreenIsDirty == true)
{
visuals->ClearScreenBufferWithColor(0, 0, 0, 255);

    visuals->Sprites[1].ScreenX = 320;
    visuals->Sprites[1].ScreenY = 240;

    visuals->Sprites[1].ScaleX = 5.0;
    visuals->Sprites[1].ScaleY = 8.0;
    visuals->Sprites[1].Smooth = false;
    visuals->DrawSpriteOntoScreenBuffer(1);

    visuals->DrawTextOntoScreenBuffer("TM", visuals->FontDefault[2]
                                      , 55, 295, JustifyRight, 1, 255, 1, 1, 1, 1);

    visuals->DrawTextOntoScreenBuffer("Bringing back old memories from the 16bit era!", visuals->FontDefault[1]
                                      , 0, 307, JustifyCenter, 1, 255, 1, 1, 1, 1);

    visuals->DrawTextOntoScreenBuffer("www.16BitSoft.com", visuals->FontDefault[0]
                                      , 0, 447, JustifyCenter, 1, 255, 1, 1, 90, 1);
}

}------------------------
JeZ+Lee
JessePalser <AT> Gmail <DOT> com
16BitSoft®
Video Game Design Studio
www.16BitSoft.com

“SDL_AddTimer” From Within A C++ Class???

Hi,

Is it possible to use “SDL_AddTimer” from within a C++ class?

Getting this error:

Code:
C:\Users\jezlee\Desktop\ChaosTimer\src\screens.cpp|21|error: argument of
type ‘Uint32 (Screens::)(Uint32, void*)’ does not match ‘Uint32 ()(Uint32,
void
)’

You need to use a C wrapper :

Uint32 process(uint32 interval, void* this)
{
Screens* theObject = (Screens*)this

this->ProcessScreenTodisplay(interval);

}

And use this function as your callback.
This is because C++ methods have an hidden “this” parameter, so they can’t be
used as C functions. Making it a static method may also work.On 2011-09-10 at 16:15:52 [+0200], JeZ-l-Lee wrote:


Adrien.

pulkomandy wrote:

On 2011-09-10 at 16:15:52 [+0200]You need to use a C wrapper :

Uint32 process(uint32 interval, void* this)
{
Screens* theObject = (Screens*)this

this->ProcessScreenTodisplay(interval);
}

And use this function as your callback.
This is because C++ methods have an hidden “this” parameter, so they can’t be
used as C functions. Making it a static method may also work.
Hi,

Thanks for the quick reply to my question.

I’m confused: where would this “C wrapper” be located?
(I tried to put it in the C++ class but it does not build)

Also, how would I make the method static? (sounds like an easier solution)
Please further explain your two solutions, thanks!------------------------
JeZ+Lee
JessePalser <AT> Gmail <DOT> com
16BitSoft®
Video Game Design Studio
www.16BitSoft.com

Is it possible to use “SDL_AddTimer” from within a C++ class?

You need to use a C wrapper :
[…]

Making it a static method may also work.

Not just “may”, but it does :slight_smile: In most cases this is enough. You can
go fancy though and do something like this:

http://www.partow.net/programming/templatecallback/index.htmlOn 09/10/2011 05:20 PM, pulkomandy at pulkomandy.ath.cx wrote:

On 2011-09-10 at 16:15:52 [+0200], JeZ-l-Lee wrote:

Uint32 Screens::ProcessScreenToDisplay(Uint32 interval, void *param)

This needs to go through a “static” method in your class declaration.

class Screens
{
Uint32 ProcessScreenToDisplay(Uint32 interval);
static Uint32 ProcessScreenToDisplayCB(Uint32 interval, void *param);
};

…being static, it won’t have access to any instance members, so you’ll
want to pass “this” so you can get the object…

 ScreenDisplayTimer = SDL_AddTimer(16, 

&Screens::ProcessScreenToDisplayCB, this);

And then in the method…

Uint32 Screens::ProcessScreenToDisplayCB(Uint32 interval, void *param)
{
return ((Screens *) param)->ProcessScreenToDisplay(interval);
}

(You can use a normal C function to do the same thing, since they don’t
have a “this” pointer. This way just keeps it all inside the class.)

–ryan.

I’ve solved this problem in SDL++. Take a look at

It uses a static function to create a trampoline that will call your timer callback.

  • chrisOn 11-09-10 10:15 AM, JeZ-l-Lee wrote:

C:\Users\jezlee\Desktop\ChaosTimer\src\screens.cpp|21|error: argument of type
’Uint32 (Screens::)(Uint32, void*)’ does not match ‘Uint32 ()(Uint32, void)’

I’m confused: where would this “C wrapper” be located?
(I tried to put it in the C++ class but it does not build)

Outside of the class. I usually put these at the end of the cpp file.

Also, how would I make the method static? (sounds like an easier solution)
Please further explain your two solutions, thanks!

Just add static to its declaration in your class

class Screens
{
static Uint32 ProcessScreenToDisplay();
}

Note a static method can’t access non-static fields of the class (it
doesn’t have the “this” pointer, so it doesn’t know which object it should
handle).
This means you wil llikely have to do the same trick as with the C
function: getting the this pointer back from the void* parameter of
addTimer, and use it for accessing the fields.

I forgot to say your addtimer call should look like :
SDL_AddTimer(16, processscreentodisplay, this);

(here we give the this pointer from the actual object, that will be
recovered).On 2011-09-10 at 16:33:33 [+0200], JeZ-l-Lee wrote:


Adrien.

Hi,

Thanks for all the suggestions!

Ok, I got it to build, but when I run it it gets stuck in an infinite loop (Not Responding)?

Here is the header file:

Code:
class Screens
{
public:

Screens(void);
virtual ~Screens(void);

#define SixteenBitSoftScreen    0
int ScreenToDisplay;
bool ScreenIsDirty;

SDL_TimerID ScreenDisplayTimer;

Uint32 ProcessScreenToDisplay(Uint32 interval);
static Uint32 ProcessScreenToDisplayCB(Uint32 interval, void *param);

void DisplaySixteenBitSoftScreen(void);

};

Here is the CPP file:

Code:
#include “SDL.h”
#include “SDL_image.h”
#include “SDL_mixer.h”
#include “SDL_ttf.h”
#include “SDL_opengl.h”

#include “screens.h”

#include “visuals.h”
#include “input.h”

extern Visuals* visuals;
extern Input* input;

//-------------------------------------------------------------------------------------------------
Screens::Screens(void)
{
ScreenIsDirty = true;
ScreenToDisplay = SixteenBitSoftScreen;

ScreenDisplayTimer = SDL_AddTimer(16, &Screens::ProcessScreenToDisplayCB, this);

}

//-------------------------------------------------------------------------------------------------
Screens::~Screens(void)
{
SDL_RemoveTimer(ScreenDisplayTimer);
}

//-------------------------------------------------------------------------------------------------
Uint32 Screens::ProcessScreenToDisplayCB(Uint32 interval, void *param)
{
return ((Screens *) param)->ProcessScreenToDisplay(interval);
}
//-------------------------------------------------------------------------------------------------
Uint32 Screens::ProcessScreenToDisplay(Uint32 interval)
{
input->GetAllUserInput();

switch(ScreenToDisplay)
{
    case SixteenBitSoftScreen:
        DisplaySixteenBitSoftScreen();
        break;


    default:
        break;
}

if (ScreenIsDirty == true)
{
    visuals->DisplayScreenBufferOntoDisplay();
    ScreenIsDirty = false;
}

return(interval);

}

//-------------------------------------------------------------------------------------------------
void Screens::DisplaySixteenBitSoftScreen(void)
{
if (ScreenIsDirty == true)
{
visuals->ClearScreenBufferWithColor(255, 0, 0, 255);

    visuals->Sprites[1].ScreenX = 320;
    visuals->Sprites[1].ScreenY = 240;

    visuals->Sprites[1].ScaleX = 5.0;
    visuals->Sprites[1].ScaleY = 8.0;
    visuals->Sprites[1].Smooth = false;
    visuals->DrawSpriteOntoScreenBuffer(1);

    visuals->DrawTextOntoScreenBuffer("TM", visuals->FontDefault[2]
                                      , 55, 295, JustifyRight, 1, 255, 1, 1, 1, 1);

    visuals->DrawTextOntoScreenBuffer("Bringing back old memories from the 16bit era!", visuals->FontDefault[1]
                                      , 0, 307, JustifyCenter, 1, 255, 1, 1, 1, 1);

    visuals->DrawTextOntoScreenBuffer("www.16BitSoft.com", visuals->FontDefault[0]
                                      , 0, 447, JustifyCenter, 1, 255, 1, 1, 90, 1);
}

}------------------------
JeZ+Lee
JessePalser <AT> Gmail <DOT> com
16BitSoft®
Video Game Design Studio
www.16BitSoft.com

Hey.

See the SDL Timer documentation. The timer may run in a separate thread.
Assuming your calls to Visuals get routed to SDL’s standard rendering model
(e.g. not OpenGL), then this is documented requiring the calls to be made
from the main thread. Even if they do not call SDL’s renderer, such
multi-threading needs to be done with care. You would need to consult the
API documentation of anything you call do see if it can be done in a
thread-safe manner.

The SDL_AddTimer documentation recommends using SDL_PushEvent() instead of
calling complex logic. Your main loop can use SDL_PollEvent or
SDL_WaitEvent() and call the appropriate rendering functions when the event
is processed.

Regards,
Brian.On 10 September 2011 16:01, JeZ-l-Lee wrote:

**

Ok, I got it to build, but when I run it it gets stuck in an infinite loop
(Not Responding)?
*
*