Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C++ (http://www.programmingforums.org/forum15.html)
-   -   Trouble with Passing Pointers to a Function. (http://www.programmingforums.org/showthread.php?t=12758)

Mcoy Mar 9th, 2007 6:44 PM

Trouble with Passing Pointers to a Function.
 
I've started working with the SDL library a couple days ago. I am writing code to take a bitmap file and display it in a 640x480 window.

The image is called "bg.bmp" (for background)

To draw things in SDL you need to set up surfaces to draw on. In my program I would need a "screen" surface to display on the screen, and a "back" surface to draw the bg.bmp image to and then draw the back surface onto the screen surface.

Trouble is occurring for me when I write a function to do that:

:

void Draw_BG(SDL_Surface *back, SDL_Surface *screen)
{
    SDL_Rect dest;
    dest.x = 0;
    dest.y = 0;
    SDL_BlitSurface(back, NULL, screen, &dest);
    SDL_Flip(screen);
}


:

int main(int argc, char *argv[])
{
    SDL_Surface *screen, *image, *back;
   
    if(Init_Engine(screen, image, back) == true)
                          return 1; // quits program if we could not load image or set screen mode
                         
    Draw_BG(back, screen);
    ....
    ....


In the above code I made a pointer to a screen and background surface.
I loaded the image to back successfully.
I passed the pointers back and screen from main to Draw_BG.
Draw_BG's back and screen pointers should now hold the same address as main's back and screen, Draw_BG should infact be working on bg.bmp and the screen. But they don't, and I get a black screen.

If I make 'back and 'screen global variables and remove the arguments to my functions then the program works correctly. So I must have made an error with passing pointers to my functions. I can't figure out what it is though....

grumpy Mar 9th, 2007 7:00 PM

I'm only guessing, as I'm not familiar with the SDL library.

But, I suspect that the problem is that the functions you're calling require the address of a SDL_Surface, rather than an uninitialised pointer. If so, your code will yield undefined behaviour. So, change main() to this;
:

int main(int argc, char *argv[])
{
    SDL_Surface screen, image, back;  // no pointers
   
    if(Init_Engine(&screen, &image, &back) == true)
                          return 1; // quits program if we could not load image or set screen mode
                         
    Draw_BG(&back, &screen);
}

As to why the code worked when you made the variables into globals: you just got lucky.

Mcoy Mar 9th, 2007 11:00 PM

The pointers screen and back are initialized to point to an SDL_Surface object when I declare them. They "point" to an SDL_Surface somewhere in dynamic memory. When I pass them to Init_Engine, Init_Engine Copies them to its own pointers and works on the same SDL_Surface objects as screen and back point to. Here is the code I wrote for init_Engine (I should have put this up in my first post).

:

int Init_Engine(SDL_Surface *screen, SDL_Surface *image, SDL_Surface *back)
{
    //Initialize SDL Engine
    if(SDL_Init(SDL_INIT_VIDEO)<0)
    {
                                  std::ofstream error("error.txt");
                                  error << "Error Initializing Engine." << "\n";
                                  return 1;
    }

    //Initialize Screen
    screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
    if(screen == NULL)
    {
              std::ofstream error("error.txt");
              error << "Error Initializing Screen." << "\n";
              return 1;
    }
   
    //Load Image and Background
    image = SDL_LoadBMP("image.bmp");
    back = SDL_LoadBMP("bg.bmp");
   
    return 0;
}


SDL_LoadBMP and SDL_SetVideoMode return SDL_Surface objects, I'm assuming to the location pointed to by screen, back and image.

P.S I'm not trying to sound like I know it all, as I've probably made some foolish mistake. I'm just trying to show you what I'm thinking.

Mcoy Mar 9th, 2007 11:31 PM

Problem Solved! Sorry for the confusing layout of my question.

My first mistake was not using
:

SDL_Surface *screen = new SDL_Surface
SDL_Surface *back = new SDL_Surface

to use dynamic memory.

Second, SDL_LoadBMP and SDL_SetVideoMode return pointers to Surface objects, not actual objects. So passing pointers to the functions wont change what they point to, as the duplicated pointer will be pointed to something else.

Benoit Mar 9th, 2007 11:36 PM

Good to see you got it solved.

grumpy Mar 10th, 2007 12:33 AM

Quote:

Originally Posted by Mcoy (Post 125034)
The pointers screen and back are initialized to point to an SDL_Surface object when I declare them.

Not according to the code you provided in your first post;
:

int main(int argc, char *argv[])
{
  SDL_Surface *screen, *image, *back;
  if(Init_Engine(screen, image, back) == true)
}

screen, image, and back were not initialised.
Quote:

Originally Posted by Mcoy (Post 125034)
They "point" to an SDL_Surface somewhere in dynamic memory.

Only if you make it happen. You have not done that. Declaring a pointer does not magically create something for a pointer to point at.
Quote:

Originally Posted by Mcoy (Post 125034)
When I pass them to Init_Engine, Init_Engine Copies them to its own pointers and works on the same SDL_Surface objects as screen and back point to. Here is the code I wrote for init_Engine (I should have put this up in my first post).

:

int Init_Engine(SDL_Surface *screen, SDL_Surface *image, SDL_Surface *back)
{
    //Initialize SDL Engine
    if(SDL_Init(SDL_INIT_VIDEO)<0)
    {
                                  std::ofstream error("error.txt");
                                  error << "Error Initializing Engine." << "\n";
                                  return 1;
    }

    //Initialize Screen
    screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
    if(screen == NULL)
    {
              std::ofstream error("error.txt");
              error << "Error Initializing Screen." << "\n";
              return 1;
    }
   
    //Load Image and Background
    image = SDL_LoadBMP("image.bmp");
    back = SDL_LoadBMP("bg.bmp");
   
    return 0;
}

SDL_LoadBMP and SDL_SetVideoMode return SDL_Surface objects, I'm assuming to the location pointed to by screen, back and image.

P.S I'm not trying to sound like I know it all, as I've probably made some foolish mistake. I'm just trying to show you what I'm thinking.

Your problem is that you are mixing up the notions of pointers and passing by value to a function. The line;
:

    screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
is local to Init_Engine(). The pointer screen within main() is passed by value to Init_Engine(), which means the value of the pointer is copied. The change of screen within Init_Engine() is not visible to main().

Using dynamic memory does not fix the problem, but it might make some of the symptoms go away (essentially because you introduce more memory to your program, and that memory gets tromped rather than something which causes a symptom you can observe at the moment).


All times are GMT -5. The time now is 2:12 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC