c++dllsingletonshared-libraries

How to handle static variable sharing in dynamic linking of libraries?


I have a requirement in which I have to use a singleton class, acting as a database to store some values. I have also declared a run function in the cpp file of this singleton class in order to change the data and print. Then, I create a shared object of this class using g++ -fPIC -shared -o lib1.so ClassA.cpp. I try to load the library and execute the run function, but a runtime error is generated due to undefined symbol. This is due to the fact that I am not declaring my static variable as nullptr in the implementation of the singleton class, rather I am trying to do it in main. The sole purpose of doing this is keep this singleton object alive in the memory of main process, so that subsequent dynamic libs which are loaded can access the same object. Is there any better way to do this? Here is my current implementation:

// ClassA.h
#ifndef _CLASSA_
#define _CLASSA_


class ClassA{
    private:
        int integer;
        static ClassA* classA;
        ClassA(){}

    public:
        static ClassA* getOrCreate();
        ~ClassA();
        int getInt();
        void setInt(int& a);
};


#endif // _CLASSA_

// ClassA.cpp
#include "ClassA.h"
#include <iostream>

ClassA* ClassA::getOrCreate() {
    if (classA == nullptr) {
        classA = new ClassA();
    }
    return classA;
}

ClassA::~ClassA() {
    delete classA;
}

int ClassA::getInt() {
    return integer;
}

void ClassA::setInt(int& a) {
    integer = a;
}


extern "C" void run() {
    int intin = 42;
    ClassA::getOrCreate()->setInt(intin);
    std::cout << "Value set: " << ClassA::getOrCreate()->getInt() << std::endl;
}

// main.cpp
#include <iostream>
#include <dlfcn.h>
#include "ClassA.h"


ClassA* ClassA::classA = nullptr;
int main() {
    void* handle = dlopen("./lib1.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "Cannot open library: " << dlerror() << std::endl;
        return 1;
    }
    typedef void (*run_func)();
    dlerror();
    run_func run = (run_func) dlsym(handle, "run");
    char* error = dlerror();
    if (error != NULL) {
        fprintf(stderr, "%s\n", error);
        dlclose(handle);
        exit(EXIT_FAILURE);
    }

    run();
    dlclose(handle);
    return 0;
}


Solution

  • I want the singleton and all the objects pointed by the pointers inside the singleton alive, even if the library gets unloaded, so that the next library can read and write on same data

    Dynamically allocated memory is not affected by dynamic loader but you do need some kind of a "root" pointer to keep a pointer to it. In your implementation it is classA. It can't be a static variable of your library if it gets unloaded since its value would be lost. So your options are limited: