2

我正在为我的 exe 和 dll 编写具有日志记录级别的单例记录器。

记录器.h:

#define LOG CLogger::GetInstance().Log
#define LOG_PATH _T(".\\LogFile\\Logger.log")
enum eLogLevel { NONE=0, ERR, WARNING, USER, SYSTEM, DEVELOPER };  

class CLogger  
{
public:
    //Construcor & Destructor
                    CLogger();
    virtual             ~CLogger();
    //Singleton 
    static CLogger&     GetInstance();          
    //For logging level preference
    //Example: WARNING -> Log only ERR & WARNING messages
    //Default = NONE
    virtual void        SetLogLevel(eLogLevel eLevel);  
    //Logging
    virtual void        Log(eLogLevel eLevelType, CString szText);  

protected:
    //Open & Close the log after used
    virtual void        CloseLog();
    virtual BOOL        OpenLog();

    CStdioFile      m_File;
    CString         m_szFile;
    eLogLevel       m_eLevel;
    BOOL            m_bFileOpened;
};

思路是,EXE项目需要包含Logger.cpp & Logger.h,负责设置日志级别。

同时,DLL工程需要包含Logger.cpp & Logger.h,但不需要设置日志级别,它会跟随EXE工程的日志级别。

预计 EXE 和 DLL 都能够将任何内容写入同一个日志文件。

现在的结果是,我需要向 DLL 项目请求 SetLogLevel() 以便 DLL 项目能够写入日志文件。

任何人都可以在上面的 Logger.h 上发现问题吗?单例不会共享一个对象实例,包括成员变量,因为 EXE 和 DLL 将在同一个进程/线程上运行?

4

2 回答 2

1

为了在 VC++ 中跨 DLL 边界共享实体(函数、对象等),您需要__declspec(dllexport)在导出它们__declspec(dllimport)的 DLL 和导入它们的 DLL 中声明它们。这通常是通过某个地方的条件定义宏来完成的:编译和链接导出器时,您将LOGGER_DLL在编译器选项的行中添加预处理器定义,并在 DLL 的通用头文件中添加,例如:

#ifdef LOGGER_DLL
#define LOGGER_EXPORTS __declspec(dllexport)
#else
#define LOGGER_EXPORTS __declspec(dllimport)
#endif

然后在类定义中:

class LOGGER_EXPORTS Logger
{
    // ...
};

(还有另外两个简短的评论:C名称的单个大写前缀是 Microsoft 约定,表示该类是在 Microsoft 库中定义的,不应在用户代码中使用;这种前缀的目的之一是避免名称冲突。并且 C++ 中的布尔类型是拼写bool的,而不是BOOL. BOOL是,我认为,微软宏,在该语言具有布尔类型之前的日子提供,并且仅出于向后兼容性的原因而存在。它应该'不能在新代码中使用。)

于 2012-04-19T09:01:40.557 回答
0

对于本例中的单例对象,它将在 EXE 和 DLL 中实例化两次。

它们都是在不同的内存地址中创建的,因此它们共享不同的成员变量。它表明它们都存在而不知道彼此。

现在,解决这个问题大概有两种方法:
1)通过将Logger类包装到DLL中来实例化唯一的ONE记录器
2)EXE和DLL分别创建实例,他们需要在EXE和DLL设置日志级别

于 2012-04-20T02:55:59.240 回答