C++ a singleton class with dll

后端 未结 2 1978
谎友^
谎友^ 2020-12-29 06:22

I created a static library with class:

class CLog
{
   private:
   CLog();
   ...
   ...
   public:
   static CLog& GetInstance()                                 


        
相关标签:
2条回答
  • 2020-12-29 06:42

    The problem is that every project that links the static library, be it main program or DLL, will get a separate copy of the static variable. This breaks the typical method of creating a singleton.

    The simplest way around this is to create another DLL which holds the singleton, rather than a static library. Since only one linker output will contain the static variable, the problem is solved.

    In my own case I created a singleton manager that identified each singleton by a unique GUID and ensured that only one copy existed application wide. The singleton manager existed as its own DLL.

    0 讨论(0)
  • 2020-12-29 06:47

    The method I used was to export a function called GetLogger from the EXE which provides a pointer to the singleton. GetInstance() implementation is conditional on the _USRDLL preprocessor define. When _USRDLL is set (for the DLL compilation) GetInstance() calls GetModuleHandle() to get a handle to the EXE and loads the function called GetLogger. Here's the code based on your example:

    Static lib has Log.h:

    class Log
    {
      private:
      Log();
    
      public:
      ~Log();
    
      static Log& GetInstance()                                
      {                 
      #ifdef _USRDLL
        typedef Log* (*GetLoggerFn)();
        HMODULE mod = GetModuleHandle( NULL );
        GetLoggerFn getLogger = (GetLoggerFn)::GetProcAddress( mod, "GetLogger" );
        Log* Instance = getLogger();
        return *Instance;
      #else
        static Log Instance;
        return Instance;
      #endif
      }
      void Write(const std::string& str );
    };
    #define LOG Log::GetInstance()
    

    Static lib has Log.cpp:

    #include "Log.h"
    
    void Log::Write(const std::string& str )
    {
        std::cout << this << "  " << str << std::endl;
    }
    
    Log::Log()
    {
    }
    
    Log::~Log()
    {
        std::cout << "Log destroyed" << std::endl;
    }
    

    DLL just has a log statement in DllMain:

    #include "../static/Log.h"
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        LOG.Write("Hello from dll");
        return TRUE;
    }
    

    And EXE looks like this:

    #include "stdafx.h"
    #include "../static/Log.h"
    #include <Windows.h>
    extern "C"
    {
        __declspec( dllexport ) Log* GetLogger()
        {
            return &LOG;
        }
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        LOG.Write("Hello from exe");
        HMODULE mod = ::LoadLibraryA( "../Debug/tdll.dll");
        ::FreeLibrary( mod );
        LOG.Write("unloaded library");
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题