SDL_rect gives error "does not name a type" when used in non-main file


#1

SDL_rect gives error “does not name a type” when used in non-main file, but wheh using the same header file in my main file it compiles fine ,
below are my header file, cpp file and also main file
header2B.h

#ifndef header2B_H
#define header2B_H

#include <SDL2/SDL.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

void SDLdisplay(char& lvl);

#endif

func2.cpp

#include "header2B.h"

extern SDL_Renderer * renderer;
extern SDL_Texture* tex;
    
    SDL_Rect text_rect2;        //giving error
	text_rect2.w = 320;
    text_rect2.h = 240;
	text_rect2.x = 0;
    text_rect2.y = 0; 

	void SDLdisplay(char& lvl){
		if(lvl){
    		SDL_Surface *surface2 = NULL;
    		surface2 = SDL_LoadBMP("/home/u-16i/Pictures/fringelogo.bmp");
			tex = SDL_CreateTextureFromSurface(renderer, surface2);
    		SDL_FreeSurface(surface2);surface2 = NULL;
        	SDL_RenderCopy( renderer, tex, NULL, &text_rect2);

			}
	}	

main.cpp

#include "header2B.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>

using namespace std;
using std::cout;
using std::endl;



int main (int argc, char* argv[])
{
    SDL_Window* window = NULL;
    SDL_Surface* surface1 = NULL;

    if (SDL_Init(SDL_INIT_VIDEO) < 0)
        { 
            cout<<"failed... sdl Init"<< SDL_GetError()<<endl;
            return -1;
        }
    window = SDL_CreateWindow("window title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320*2, 240*2, SDL_WINDOW_SHOWN |SDL_WINDOW_BORDERLESS);
    
    if (window == NULL)
        {
            cout<<"failed... window"<< SDL_GetError()<<endl; 
            return -1;
        }
    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED  );
    if (renderer == NULL)
        {
            std::cerr << "Error creating window or renderer: " << SDL_GetError() << std::endl;
            SDL_Quit();
            return 1;
        }

	SDL_Event e;
    bool quit = false;	

    SDL_Rect    text_rect;          //but it is not giving error
	text_rect.w = 320;
    text_rect.h = 240;
	text_rect.x = 100;
    text_rect.y = 100; 

    SDL_Surface *surface = NULL;


    surface1 = SDL_LoadBMP("/home/u-16i/Pictures/fringelogo.bmp");
	SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, surface1);
    SDL_FreeSurface(surface1);surface1 = NULL;
    
    char lvlM=1;
    SDLdisplay(lvlM);

    while (!quit)
    {
        while (SDL_PollEvent(&e))
		{
            switch (e.type)
            {
                case SDL_KEYDOWN:
                    switch (e.key.keysym.sym)
                    {
                        case SDLK_ESCAPE:

							quit = true;
                            break;

                    
                    }
                    break;
            }
        }

		SDL_RenderClear(renderer);    	
        SDL_RenderCopy( renderer, tex, NULL, &text_rect);
      	SDL_RenderPresent(renderer); 
	}

    SDL_DestroyTexture(tex);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

what can be the possible reasons?? how to make it work, any help …


#2

Check the specific line you’re getting from your compiler. Hint: on mine (clang) it errors not on the SDL_Rect text_rect2 line, but the one after it

(it’s because you can’t initialize a struct outside of a function line by line like that; use an initializer list, like SDL_Rect text_rect2 = { 0, 0, 320, 240 };. You don’t get the error in main.cpp because you’re doing the line-by-line rect initialization inside a function).


#3

thank you, it compiled finally, but with now error comes in linking stage.
those sdl variables that i have externed from main file(where i have initialized it) is giving undefined reference to error.
g++ -std=c++17 -g -Wall 2SDL_extern.cpp header2.h header2B.h 2cppsdlfunc.cpp -o SDL2 $(pkg-config --cflags --libs sdl2) -lSDL2_ttf
error:
/tmp/cc7yA8ba.o: In function SDLdisplay(char&):
/home/u-16i/Documents/aka/linux/SDL2/2cppsdlfunc.cpp:17: undefined reference to renderer
/home/u-16i/Documents/aka/linux/SDL2/2cppsdlfunc.cpp:17: undefined reference to tex
/home/u-16i/Documents/aka/linux/SDL2/2cppsdlfunc.cpp:19: undefined reference to tex
/home/u-16i/Documents/aka/linux/SDL2/2cppsdlfunc.cpp:19: undefined reference to renderer
collect2: error: ld returned 1 exit status

do datatypes of sdl2 cannot be externed?


#4

You’ve declared them, but not defined them anywhere. Declaring an extern variable just says that there will be a variable defined in another module, but does not allocate storage for it. The variables of the same name that you’ve created in your main() function aren’t the same (local variables with the same name as a global variable hide the global variable). In main.cpp define the variables, somewhere before your main() function:

SDL_Renderer *renderer;
SDL_Texture *tex;

and then remove their declarations inside main().

However, using global variables to pass around data like this is terrible API design and will lead to only misery (you’ve already got a memory leak from it: you create a texture and assign it to tex, but then you call SDLdisplay(), which creates a new texture and assigns it to tex, and loses the pointer to tex’s original texture, so it can’t be destroyed until your game exits).

Instead just pass in the renderer as an argument to SDLdisplay():

header2b.h
#ifndef HEADER2B_H_
#define HEADER2B_H_

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

SDL_Texture *SDLdisplay(char lvl, SDL_Renderer *renderer);

#endif


func2.cpp

#include "header2B.h"

SDL_Texture *SDLdisplay(char lvl, SDL_Renderer *renderer)
{
    SDL_Surface *surface = SDL_LoadBMP("/home/whatever/somepicture.bmp");
    if(surface == nullptr) {
        return nullptr;
    }
    SDL_Texture *tex = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_FreeSurface(surface);

    return tex;
}


main.cpp

all the same stuff until you call SDLdisplay(), but remove the stuff right
before it where you load the same image that SDLdisplay() is going to load. Then:

    char lvlM = 1;
    SDL_Texture *tex = SDLdisplay(lvlM, renderer);

then the same everything else afterwards

edit: have tested this code, it compiles and works


#5

thank you, it was much useful