Search code examples
cgccheaderguard

C Guard not work as intended with rlutil.h


I'm trying to use rlutil.h but everytime these function are used in more than one header I have compiler error about multiple definition of 20-30 variables. rlutil is a simple header to color terminal in linux and windows in C and C++.

The variables are something like that

const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST = "\007";

and the typedef something like that

typedef const char* RLUTIL_STRING_T;

I tried to add my own C guard but it didn't worked. I tried to layering the .h with my own .h/.c to make new function using the rlutil.h function but the problem is still here. I tried to make the variables extern but it's worst

I'm building it with gcc on ubuntu. I'm gonna try this at home with MVSC2017 but I think the behavior will be the same.

Any idea ?

I can provide more information. Sorry for my english i'm not a native speaker

Thank's a lot


Solution

  • The problem is that the header is only set up so that it works with C++, where the const values defined in the header rlutil.h are private to each translation unit (TU) — think source file plus headers — that includes the header. By contrast, in C, they are normal global variables defined in each TU that includes rlutil.h, leading to the multiple definitions problem.

    There isn't a trivial fix — unless switching from C to C++ is deemed trivial. The header attempts to be language-neutral between C and C++, but it fails on this count. Once again, proof that C and C++ are different languages.

    In C, you would need to have code like:

    extern const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST;
    

    in the header and then one source file would define the values:

    const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST = "\007";  // James Bond!
    

    Alternatively, you could consider using static in the header:

    static const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST = "\007";
    

    Each C file that includes this header would have its own collection of defined variables. In C, you'd be subject to compiler warnings about unused variables, which is not desirable. In C++, you might get warnings about using static instead of an anonymous namespace. It isn't clear that this is a good solution, therefore.

    If you're brave, you could read the tail end of my answer to How do I use extern to share variables between files, but the header is probably not in your control and you really need to report the trouble to the maintainers of the code. (If you are the maintainer, then think about whether a scheme such as that outlined in the answer to the other question will help.)