Search code examples
cstructsdl

How to handle structs/abstract data types in multiple files in C/SDL2


I'm working on this graphics/game engine with SDL2 and C.

I manage to code all the basis for the game loop and I have things split in multiple files. A problem appeared when I tried defining my own data types (structs in this case). I have my struct (vector3) definition and declaration in tad.h and tad.c, but I'm having problems with creating variables with this vector3 type. I tried declaring this ponto1 in my main file, and I'm trying to use it in my other files as a global variable, but I'm getting some errors.

I want to be able to declare my own structs and pointers to structs, but I'm new to working in C with multiple files like this. Here are the files and problems I'm getting: (PS: tips on how to structure better my program are welcome as well)

tad.h:

#ifndef TAD
#define TAD

typedef struct vector3 Vector3;

#endif

tad.c:

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

#include "./tad.h"
#include "./constants.h"
#include "./globals.h"

struct vector3 {
    float x;
    float y;
    float z;
};

globals.h:

extern SDL_Window* my_window;
extern SDL_Renderer* my_renderer;

extern int game_is_running;

extern Vector3 ponto1;

main.c

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


#include "./constants.h"
#include "./globals.h"
#include "./tad.h"
#include "./init_and_destroy.h"
#include "./setup.h"
#include "./process_input.h"
#include "./update.h"
#include "./render.h"

SDL_Window* my_window = NULL;
SDL_Renderer* my_renderer = NULL;
int game_is_running = FALSE;

Vector3 ponto1;


int main() {
    
    game_is_running  = initialize_window(&my_window, &my_renderer);
    
    setup();

    while(game_is_running) {
        process_input();
        update();
        render();
    }

    destroy_window(my_window, my_renderer);

    return 0;
}

update.c

#include "./constants.h"
#include "./globals.h"
#include "./tad.h"
#include "./update.h"

int last_frame_time = 0;

void update() {
    
    //caping frame rate
    int time_to_wait = FRAME_TARGET_TIME - (SDL_GetTicks() - last_frame_time);
    if (time_to_wait > 0 && time_to_wait <= FRAME_TARGET_TIME) {
        SDL_Delay(time_to_wait);
    }

    //delta time in seconds
    float delta_time = (SDL_GetTicks() - last_frame_time) / 1000.0f;

    last_frame_time = SDL_GetTicks();

//-------------------------------------------------------------------------------------

    ponto1.x += 20 * delta_time; //I'M TRYING TO ACCESS AND CHANGE THIS STRUCT

}

The erros I get:

./src/./globals.h:6:8: error: unknown type name ‘Vector3’
    6 | extern Vector3 ponto1;
      |        ^~~~~~~
In file included from ./src/main.c:6:
./src/./globals.h:6:8: error: unknown type name ‘Vector3’
    6 | extern Vector3 ponto1;
      |        ^~~~~~~
./src/main.c:18:9: error: conflicting types for ‘ponto1’; have ‘Vector3’ {aka ‘struct vector3’}
   18 | Vector3 ponto1;
      |         ^~~~~~
In file included from ./src/main.c:6:
./src/./globals.h:6:16: note: previous declaration of ‘ponto1’ with type ‘int’
    6 | extern Vector3 ponto1;
      |                ^~~~~~
./src/main.c:18:9: error: storage size of ‘ponto1’ isn’t known
   18 | Vector3 ponto1;
      |         ^~~~~~
In file included from ./src/process_input.c:4:
./src/./globals.h:6:8: error: unknown type name ‘Vector3’
    6 | extern Vector3 ponto1;
      |        ^~~~~~~
In file included from ./src/render.c:5:
./src/./globals.h:6:8: error: unknown type name ‘Vector3’
    6 | extern Vector3 ponto1;
      |        ^~~~~~~
./src/render.c: In function ‘render’:
./src/render.c:16:44: error: request for member ‘x’ in something not a structure or union
   16 |     SDL_RenderDrawPoint(my_renderer, ponto1.x, 50);
      |                                            ^
In file included from ./src/setup.c:5:
./src/./globals.h:6:8: error: unknown type name ‘Vector3’
    6 | extern Vector3 ponto1;
      |        ^~~~~~~
./src/setup.c: In function ‘setup’:
./src/setup.c:11:11: error: request for member ‘x’ in something not a structure or union
   11 |     ponto1.x = 3;
      |           ^
In file included from ./src/update.c:5:
./src/./globals.h:6:8: error: unknown type name ‘Vector3’
    6 | extern Vector3 ponto1;
      |        ^~~~~~~
./src/update.c: In function ‘update’:
./src/update.c:26:11: error: request for member ‘x’ in something not a structure or union
   26 |     ponto1.x += 20 * delta_time;
      |           ^
make: *** [Makefile:2: build] Error 1

Solution

  • You're getting an error because globals.h uses the type Vector3 but that type hasn't been defined at that point.

    You need to #include "tad.h" in globals.h since it uses types defined there.

    The other problem you're seeing is because in files where tad.h is included and it uses fields of Vector3, the struct that the type refers to has been declared but not defined. You need to move the struct definition out of tad.c and into tad.h so other files can use it.