views:

233

answers:

3

Hello there,

I'm new on C++ and I'm trying to make some testing with C++ and SDL and in SDL we have a function:

SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param);

which I can pass a callback for the timer created. But apparently it converts my instance this to *void so I can't retrieve it again on the update method which is static, and it's interesting but the the SDL_AddTime doesn't work on a non static callback function.

Well, so my problem is that when trying to call the public method render through the void* param argument It complains about not being a pointer-to-object-type...

Is there any way I can get the Character instance again inside the update method since I don't have control over the SDL_AddTime function and I have to pass the required parameters?

Thanks

#include "Character.h"

Character::Character(void)
{
  timer = SDL_AddTimer(33, update, this);
  this->render(); // is called without problem
}

//static method
Uint32 Character::update(Uint32 interval,void* param)
{
  param->render(); // yields: 'void*' is not a pointer-to-object type;

  SDL_Event event;

  event.type = SDL_USEREVENT;
  event.user.code = 1020;
  event.user.data1 = param;

  SDL_PushEvent(&event);

  return interval;
}

void Character::render(void)
{
  printf("rendering character \n");
}
+2  A: 

Cast your param pointer to a Character:

Character * charPtr = reinterpret_cast<Character *>(param);
charPtr->render();
Ron Warholic
+2  A: 

The reason is that C++ is a strong typed language. To change one type to another, you need to cast it first:

Uint32 Character::update(Uint32 interval, void* param)
{
    reinterpret_cast<Character* >(param)->render();

    /* ... */
}
LiraNuna
+4  A: 

You don't need a reinterpret_cast - a static_cast should be OK:

Character * cp = static_cast <Character *>( param );

You should avoid reinterpret_cast - it is almost always implementation specific, and may hide problems - just like old-style C casts.

anon
But isn't `static_cast` made with no type checks or anything, making it just like the C-style casts?
LiraNuna
No, it isn't - the rules are a bit complicated, but it does what STATIC (i.e. compile-time) checking it can. Otherwise, it would be identical with reinterpret_cast.
anon
Ironically, Lira, that's what `reinterpret_cast` does. `reinterpret_cast` says "treat X as Y" and the compiler goes "Ok!". `static_cast` says "Treat X as Y, but make sure this conversion is defined and use that method." and the compiler either goes "Ok, I see how" or "Nope.". For pointers, you can implicitly cast from `T*` to `void*`, and `static_cast` the other way.
GMan
This is one of the situation where I would absolutely use reinterpret_cast<>(). The static_cast<>() does not give you any more safety (because all the checks are compile time) and by using reinterpret_cast<>() you are explicitly documenting that you are doing something that is dangerous.
Martin York
Martin: Though for null pointers that have different (non-zero) representations for different types (not that I know of any such real systems myself.. but I believe it's allowed by the standard), won't reinterpret\_cast do the *wrong* thing and static\_cast work correctly?
Roger Pate
I believe the standard does guarantee that NULL pointers are 0: N2521=08-0031: 18.1.3: The macro NULL is an implementation-defined C++ null pointer constant. 4.10.1: A null pointer constant is an integral constant expression rvalue of integer type that evaluates to zero.
Martin York
GMan: Thanks for the explanation, learned something new today :)
LiraNuna
@Martin Let's not start that one again. You are confusing the zero used in the code with the internal rep of the null pointer.
anon