Sign in to follow this  

SDL threads

This topic is 3292 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Here's the example program I got from here: http://lazyfoo.net/SDL_tutorials/lesson33/index.php
/*This source code copyrighted by Lazy Foo' Productions (2004-2008) and may not
be redestributed without written permission.*/

//The headers
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_thread.h"
#include <string>

//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces
SDL_Surface *image = NULL;
SDL_Surface *screen = NULL;

//The event structure
SDL_Event event;

//The thread that will be used
SDL_Thread *thread = NULL;

//Quit flag
bool quit = false;

SDL_Surface *load_image( std::string filename ) 
{
    //The image that's loaded
    SDL_Surface* loadedImage = NULL;
    
    //The optimized surface that will be used
    SDL_Surface* optimizedImage = NULL;
    
    //Load the image
    loadedImage = IMG_Load( filename.c_str() );
    
    //If the image loaded
    if( loadedImage != NULL )
    {
        //Create an optimized surface
        optimizedImage = SDL_DisplayFormat( loadedImage );
        
        //Free the old surface
        SDL_FreeSurface( loadedImage );
        
        //If the surface was optimized
        if( optimizedImage != NULL )
        {
            //Color key surface
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
        }
    }
    
    //Return the optimized surface
    return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
    //Holds offsets
    SDL_Rect offset;
    
    //Get offsets
    offset.x = x;
    offset.y = y;
    
    //Blit
    SDL_BlitSurface( source, clip, destination, &offset );
}

bool init()
{
    //Initialize all SDL subsystems
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
    {
        return false;    
    }
    
    //Set up the screen
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
    
    //If there was an error in setting up the screen
    if( screen == NULL )
    {
        return false;    
    }
    
    //Set the window caption
    SDL_WM_SetCaption( "Thread test", NULL );
    
    //If everything initialized fine
    return true;
}

bool load_files()
{
    //Load the image
    image = load_image( "image.png" );
    
    //If there was an error in loading the image
    if( image == NULL )
    {
        return false;    
    }
    
    //If everything loaded fine
    return true;    
}

void clean_up()
{
    //Stop the thread
    SDL_KillThread( thread );
    
    //Free the surface
    SDL_FreeSurface( image );
    
    //Quit SDL
    SDL_Quit();    
}

int my_thread( void *data )
{
    //While the program is not over
    while( quit == false )
    {
        //Do the caption animation
        SDL_WM_SetCaption( "Thread is running", NULL );
        SDL_Delay( 250 );
        
        SDL_WM_SetCaption( "Thread is running.", NULL );
        SDL_Delay( 250 );
        
        SDL_WM_SetCaption( "Thread is running..", NULL );
        SDL_Delay( 250 );
        
        SDL_WM_SetCaption( "Thread is running...", NULL );
        SDL_Delay( 250 );
    }
    
    return 0;    
}

int main( int argc, char* args[] )
{
    //Initialize
    if( init() == false )
    {
        return 1;    
    }
    
    //Load the files
    if( load_files() == false )
    {
        return 1;    
    }
    
    //Create and run the thread
    thread = SDL_CreateThread( my_thread, NULL );
    
    //Apply the image to the screen
    apply_surface( 0, 0, image, screen );
    
    //Update the screen
    if( SDL_Flip( screen ) == -1 )
    {
        return 1;    
    }
    
    //While the user hasn't quit
    while( quit == false )
    {
        //While there's events to handle
        while( SDL_PollEvent( &event ) )
        {
            //If the user has Xed out the window
            if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }    
        }
    }
    
    //Clean up
    clean_up();
        
    return 0;    
}


But what if I want to pass an array of integers to the thread? How do I do that? Doesn't it have something to do with argc and argv[] or something? Like argv is an array of everything passed to the function and argc is the number of arguments? I can't remember. But why is the SDL thread above only taking a *void? I don't get it. [Edited by - icecubeflower on December 6, 2008 12:07:16 PM]

Share this post


Link to post
Share on other sites
Data has to be passed via the void pointer which in this instance would require a c style or C++ (reinterpret_cast) cast, talking of which that code should not compile, are you sure that is the code from lazy foo?
SDL_CreateThread has either two or four arguments never three(two is the portable way of calling the function) and the function pointer passed to the function has to be of the form "int (*)(void *)".

Quote:
why is the SDL thread above only taking a *void?
The reason for the void pointer is because it is a C library and this is the C method of passing any type of argument to the function.

Share this post


Link to post
Share on other sites
Okay I tried your typecasting idea, that works:

/*This source code copyrighted by Lazy Foo' Productions (2004-2008) and may not
be redestributed without written permission.*/


//The headers
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_thread.h"
#include <string>

//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces
SDL_Surface *image = NULL;
SDL_Surface *screen = NULL;

//The event structure
SDL_Event event;

//The thread that will be used
SDL_Thread *thread = NULL;

//Quit flag
bool quit = false;

SDL_Surface *load_image( std::string filename )
{
//The image that's loaded
SDL_Surface* loadedImage = NULL;

//The optimized surface that will be used
SDL_Surface* optimizedImage = NULL;

//Load the image
loadedImage = IMG_Load( filename.c_str() );

//If the image loaded
if( loadedImage != NULL )
{
//Create an optimized surface
optimizedImage = SDL_DisplayFormat( loadedImage );

//Free the old surface
SDL_FreeSurface( loadedImage );

//If the surface was optimized
if( optimizedImage != NULL )
{
//Color key surface
SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
}
}

//Return the optimized surface
return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
//Holds offsets
SDL_Rect offset;

//Get offsets
offset.x = x;
offset.y = y;

//Blit
SDL_BlitSurface( source, clip, destination, &offset );
}

bool init()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return false;
}

//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

//If there was an error in setting up the screen
if( screen == NULL )
{
return false;
}

//Set the window caption
SDL_WM_SetCaption( "Thread test", NULL );

//If everything initialized fine
return true;
}

bool load_files()
{
//Load the image
image = load_image( "image.png" );

//If there was an error in loading the image
if( image == NULL )
{
return false;
}

//If everything loaded fine
return true;
}

void clean_up()
{
//Stop the thread
SDL_KillThread( thread );

//Free the surface
SDL_FreeSurface( image );

//Quit SDL
SDL_Quit();
}

int my_thread( void *data)
{
//While the program is not over
while( quit == false )
{
//Do the caption animation
SDL_WM_SetCaption( (char*)data, NULL );
SDL_Delay( 250 );

SDL_WM_SetCaption( "Thread is running.", NULL );
SDL_Delay( 250 );

SDL_WM_SetCaption( "Thread is running..", NULL );
SDL_Delay( 250 );

SDL_WM_SetCaption( "Thread is running...", NULL );
SDL_Delay( 250 );
}

return 0;
}

int main( int argc, char* args[] )
{
//Initialize
if( init() == false )
{
return 1;
}

//Load the files
if( load_files() == false )
{
return 1;
}

//Create and run the thread
char blah[3];
strcpy(blah,"hi\0");
thread = SDL_CreateThread( my_thread,blah);

//Apply the image to the screen
apply_surface( 0, 0, image, screen );

//Update the screen
if( SDL_Flip( screen ) == -1 )
{
return 1;
}

//While the user hasn't quit
while( quit == false )
{
//While there's events to handle
while( SDL_PollEvent( &event ) )
{
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = true;
}
}
}

//Clean up
clean_up();

return 0;
}



I see it say "hi" at the top now.

So... what if you want to pass more than one argument? Do you have to declare a struct or class with all the arguments you want in it and then just pass one void pointer like last time? That seems kind of dumb.

Could I declare a pointer that points at an array of void pointers and pass it? And then just typecast the hell out of everything? ...I'm gonna try that. Someone tell me if I'm going down the wrong path.

Share this post


Link to post
Share on other sites
Generally, it's best to leave threads well alone unless you know what you're doing. For example, you shouldn't really read a variable in one thread which you're writing in another, nor should you ever use SDL_KillThread except in extreme conditions, nor pass a variable you create on the stack to another thread. It's also pointless adding that extra zero to the end of that string. And when using a function pointer, take its address with the & operator, don't just pass in its name as that's not portable to all compilers.

Share this post


Link to post
Share on other sites

This topic is 3292 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this