2012-05-08 11 views
0

私のアプリケーションでカスタムイベントを追跡するためにSDL User Eventsを使用したいと思います。私の問題は、SDL_UserEvent構造体が1つのintと2つのvoidポインタしか提供しないことです。独自のSDLイベント構造体を作成するのは安全ですか?

私は次のような構造を持つイベント持っていることを好むだろう
 
typedef struct{ 
    Uint8 type; 
    int code; 
    void *data1; 
    void *data2; 
} SDL_UserEvent; 

:私は、私はMAPイベントを処理したいとき、構造体をreinterpret_castは、私ならば、追加の処理をすることなく、メッセージを捨てることができ

 
typedef struct{ 
    Uint8 type; /* Set to SDL_USEREVENT + MAP */ 
    int code; /* Set to MAP_COLLISION */ 
    Uint8 tile_x; 
    Uint8 tile_y; 
    Uint8 tile_type; 
} UserEvent_MapCollision; 

をしないでください。私のイベントハンドラは、このテクニックを使って簡略化されます(mallocを必要とせず、この構造体を解放してイベントにアタッチする必要はありません)。

sizeof(UserEvent_MapCollision) <= sizeof(SDL_Event)が(ビルド時に)チェックされ、SDLイベントキューはプッシュされたイベントを何らかの形で変更しない限り、これは機能しますか?

+0

...より良いイベントクラスを使用してください。 http://drrobsjournal.blogspot.co.uk/ – Robinson

答えて

2

はい、それは動作しますが、 SDL_Event構造体自体が大きなunionであることに注意してください。あなたはあなたの構造体がSDL_Eventに収まるかどうかわからない場合は、このコンパイル時にアサートすることができます:sizeof(UserEvent_MapCollision) <= sizeof(SDL_Event)

/* Push event */ 
SDL_Event e; 
UserEvent_MapCollision* p = static_cast<UserEvent_MapCollision*>(&e);; 

e.type = SDL_USEREVENT + MAP; 
e.code = MAP_COLLISION; 
p.tile_x = 10; 
p.tile_y = 20; 
p.tile_type = 7; 

/* Receive event */ 
SDL_Event e; 
while (SDL_PollEvents(&e)) { 
    if (e.type == SDL_USEREVENT + MAP) { 
     if (e.user.code == MAP_COLLISION) { 
      UserEvent_MapCollision *p = static_cast<UserEvent_MapCollision>(&e) 
      HandleMapCollision(p); 
     } 
    } 
} 

コンパイル時に使用すると、SDLマクロSDL_COMPILE_TIME_ASSERTを使用することができます主張を確認するには、それはSDL_stdinc.hで定義されている:サイドノートとして

SDL_COMPILE_TIME_ASSERT(UserEvent_MapCollision, sizeof(UserEvent_MapCollision) <= sizeof(SDL_Event)); 

、これら2つのvoid*ポインタが別の構造体を参照することを意図しています。

typedef struct { 
    Uint8 tile_x; 
    Uint8 tile_y; 
    Uint8 tile_type; 
} MyCustomEventStruct; 

/* Create event */ 

SDL_UserEvent e; 
MyCustomEventStruct *p; 

p = new MyCustomEventStruct; 
p->tile_x = 10; 
p->tile_y = 20; 
p->tile_type = 7; 

e.type = SDL_USEREVENT + MAP; 
e.code = MAP_COLLISION; 
e.data1 = p; 
e.data2 = 0; 

SDL_PushEvent(&e); 

/* Receive Event */ 

while (SDL_PollEvents(&e)) { 
    if (e.type == SDL_USEREVENT + MAP) { 
     if (e.user.code == MAP_COLLISION) { 
      MyCustomEventStruct* p = static_cast<MyCustomEventStruct*>(e.user.data1); 
      HandleMapCollision(p); 
      delete p; 
     } 
    } 
} 
+0

私はOPがこれを知っていると思っていますが、可能ならばそれを避けるために探しています: "mallocする必要はなく、この構造体を解放してイベントに接続してください" – IronMensan

+0

@ vz0あなたは知っていますか?コンパイル時にsizeof(UserEvent_MapCollision)<= sizeof(SDL_Event)をチェックする方法は? – Martin

+0

@Martin: 'boost :: static_assert'または条件が満たされない場合に' int array [-1]; 'を生成する条件テンプレートのメタプログラミングです。 – SigTerm

1

それが動作するかもしれませんが、私はあなたが関数やマクロでこのような何かをやったほうが良いと思います。

Uint8 tile_x = static_cast<Uint8>(reinterpret_cast<uintptr_t>(sdl_event->data1) & 0xFF); 
Uint8 tile_y = static_cast<Uint8>((reinterpret_cast<uintptr_t>(sdl_event->data1) >> 8) & 0xFF); 
Uint8 tile_type = static_cast<Uint8>((reinterpret_cast<uintptr_t>(sdl_event->data1) >> 16) & 0xFF); 

と、この:

sdl_event->data1 = reinterpret_cast<void *>(
    static_cast<uintptr_t>(tile_x) | 
    static_cast<uintptr_t>(tile_y) << 8 | 
    static_cast<uintptr_t>(tile_type) << 16); 
関連する問題