cdata-structuresarduinoesp32include-guards

Where to store display data in a C Project


I am writing a C-Program for an Esp32, to display some Images on a 8x32 LED-Matrix. I struggle to store the Image Data in a way, that different .cpp files have access to it, but it won't lead to include-Errors

Images are stored in data.h e.g. like this:

byte A[] = {
0, 0, 0, 0, 0, 0, 0, 0, 
0, 1, 1, 1, 1, 1, 0, 0, 
0, 1, 0, 0, 1, 0, 0, 0, 
0, 1, 1, 1, 1, 1, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0,  };

The Project is getting big, so I wanted to separate main.cpp and the IR-Control and Game-Logic (I also programmed Snake on it).

So the Folder Structure is e.g. like this:

The Problem is, that in snake.cpp the data.h is imported as well as in game_of_life.cpp and others. I also tried to seperate .h and .cpp, I h've had the declaration like extern byte A[32]; in the data.h, and a seperate data.cpp with the code from above. But this also leads to conflicting declaration e.g.

src/led_matrix_color_data.cpp:2:20: error: conflicting declaration 'uint32_t A_color [48]'
 uint32_t A_color[48] = {
                ^
In file included from src/led_matrix_color_data.cpp:1:
include/led_matrix_color_data.h:5:13: note: previous declaration as 'byte A_color [48]'
 extern byte A_color[48];
             ^~~~~~~

It does not matter, if I use Include Guards, or #pragma once in the data.h, because the data is defined there, so they will be just ignored or some kind.


In what way could I store the Data, so it is easily accessible from other .cpp files (e.g. globally defined) but does not run into include-Errors?

Thanks ~Alex


Solution

  • Looking at the error messages, there's a difference between the datatypes uint32_t and byte. Read those carefully!


    To achieve consistency of all things in all places, put the data into its own file that interested other files can "see".

    // data.h
    #ifndef DATA_H
    #define DATA_H
    
    #ifdef GO_LIVE
    #define GLOBAL        // real meat-and-potatoes variables initialised
    #else
    #define GLOBAL extern // "phantom" declarations of things "out there somewhere"
    #endif
    
    GLOBAL byte arrayX[]; // forward declaration
    
    #endif
    

    and

    // data.cpp - a "pure data" source file
    
    #define GO_LIVE  // I am the meat-and-potatoes
    #include "data.h"
    
    GLOBAL byte arrayX[ 48 ] = { // token GLOBAL is simply whitespace here...
        ...
    };
    
    // and other "global" data definitions
    

    and

    // main.cpp
    
    #include < standard C or C++ headers >
    
    #include "data.h" // Let me "see" all those "extern" declarations
    ...
    int main( void ) {
    ...
    

    There are other convenient ways to achieve this, but this will get you started. Once your mind has got the concept, you'll be able to share (or not) data and functions across multiple source files as suits your needs. When writing that code, always remember the KISS principle - "Keep It Simple Stupid". Putting in clever complexity (because you can) is tantamount to digging your own future grave.

    One no-no in C code is putting data definitions into header files. Gurus and wizards are exempt, but mere mortals must always ensure that header file contents are only "globally used" tokens (#define or enum) or declarations of function prototypes or the datatypes of variables. Header files are meant to be included in multiple code files, but you don't want the linker to find multiple (duplicate) definitions of data variables.


    Given that the file names smell like some sort of "public library" collection of functions, it looks like you've got a bad bit of code from somewhere. It's not unusual for code to be published (rushed) as if it is functional when it has problems that have not been resolved. (Even some UV'd SO "answers" turn out to fall short of expectations when actually downloaded and tried!) While it is nifty-nifty to impress one's classmates with a DIY game, you should be basing your learning on more solid foundations than what you can download from the internet.

    Suggest you put the ESP32 in a box for a few months.
    Spend time immersing yourself in C/C++ to learn the language.
    The concepts needed to "include" header files are NOT the same as Python's "import".