15

I'm writing a header-only logger library and I need global variables to store current logger settings (output flags, log file descriptor etc.). My thoughts:

  • I can't declare variables as extern, as i don't have access to the translation units to define them
  • I can't just define global variables in header as it will lead to multiple definitions
  • static variables in header's functions may seem good at the first glance, but the fact is that every translation unit will have it's own copy of 'global' variable, which is awkward and definitely wrong
  • I don't also think it is possible to avoid global variables in my case (even though that's what i'd like to do) as i obviously have to store settings somehow between log function calls

Is there any variants i didn't consider yet? Is there any other way to have global variables using headers only.

p.s. I'm looking for both c99/c++11 compatible solution with possible gcc hacks (gcc >= 4.8)

13
  • 4
    If you program in C++ then please only tag C++. Commented Jul 31, 2018 at 11:59
  • As for your problem, have you considered the singleton pattern? It's very common for loggers, and can easily be adapted to hold "global" data for a header-only library. Commented Jul 31, 2018 at 12:00
  • @Someprogrammerdude i added special note to say that i'm looking for both c/c++ solution Commented Jul 31, 2018 at 12:01
  • Lastly,, why are you making your own logging library? There are plenty out there already? What use-case will your library solve that can't be solved by others? Or is it just an exercise or learning experience? Commented Jul 31, 2018 at 12:01
  • 3
    You do know that C and C++ are two very different languages? Solutions using C++ might not be possible to use in C, and the opposite (though that's more unlikely). Commented Jul 31, 2018 at 12:02

2 Answers 2

14

One approach is to hide options behind a function that returns a reference to a local static option. As long as the ODR is not violated (e.g. by some macro-dependent changes of the functions), it is guaranteed that the local static variables are unique across your program. As a simple example, this can be in the header file:

inline bool& someOption()
{
   static bool opt = false;

   return opt;
}

and in a translation unit:

someOption() = true;

It would probably be useful to group your options into a struct and apply the above technique to an instance to this struct.

Note that this approach is limited to C++ (thanks to @rici for the hint), and might only accidently work out in C using gcc.

Sign up to request clarification or add additional context in comments.

11 Comments

I wrote about this approach in my question. I can't add code to translation units as i have header only library
@Indev29 Only the first snippet is for the header file. The one-liner to demonstrate the usage in a translation unit is client code, not your library.
i get it, this is Meyer's singleton which will work for c++ and what about c realization?
@Indev29 Return a pointer, and use a macro that dereferences the value returned by the function? Like is usually done for errno.
@lubgr: C++ makes that guarantee but C specifies the opposite: "Since an inline definition is distinct from the corresponding external definition and from any other corresponding inline definitions in other translation units, all corresponding objects with static storage duration are also distinct in each of the definitions." (Footnote 140 in section 6.7.4). If you have been using this approach in C without problems, it might be because GCC by default implements non-standard semantics.
|
7

Structure your library like follows:

MyLibrary.h:

extern int foo;
extern int bar;
...
#ifdef MY_LIBRARY_IMPL
int foo;
int bar;
...
#endif

Then, in the library documentation, specify that in exactly one translation unit, the user of the library should #define MY_LIBRARY_IMPL before including the header file.

2 Comments

That's why you need to appropriate one of the end-user's header files for this purpose.
This works in C. It's a bit what Mircosoft uses to declare libraries (i.e. do you import or do you export?)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.