Search code examples
c++global-variablesdynamic-linkingdynamic-libraryheader-only

C++ header-only with global state in a shared library


I'm working on a C++ library that I would ideally keep header-only.

A specific part of this library requires a global state.
Let's say it needs a global vector of strings for this example.

I can easily achieve this with a static variable inside a function:

std::vector< std::string > & GetGlobalStrings( void )
{
    static auto g = new std::vector< std::string >();

    return *( g );
}

This works great for executables using the library.

Now for some reason, I also need to package that library inside a macOS framework.

Inside that framework, there's compiled code that will access this global state.
So does the executable linked with that framework.

Obviously this doesn't work, as the executable and the framework will have separate definitions for the static variable, thus making this global state not so global.

Is there any way to accomplish this in a convenient manner?


Solution

  • You could force the symbols to be in only one file, for instance:

    #if defined(I_NEED_A_BAD_HACK) || defined(GLOBAL_STATE_STORE)
    # define USE_FULL_FUNCTION
    #endif
    
    #ifdef USE_FULL_FUNCTION
    std::vector< std::string >& GetGlobalStrings()
    {
        static std::vector< std::string > g;
    
        return g;
    }
    #else
    std::vector< std::string >& GetGlobalStrings();
    #endif
    

    Then in one of your framework cpp, define the macro before including the header.

    Now, if you need to export the symbol (Windows mainly but also Linux/macOS with visibility hidden), then it gets a little bit trickier, as you need another global flag saying if you are in the framework or not and activating the export/import attribute.

    It's definitely not great, but at least you ensure that you have only one instance of the static variable in one file. Also works properly with a static library, of course.