如何在VC10中使用具有跨DLL边界的静态数据成员的模板类



我有一个Logging类,它可以简化为:

template <int TARGET>
struct Logging
{
  static ostream * sOstream;
  static void log(const char * _txt);
  static void set_log_file(const char * _file_name)
  {
     sOstream = new ofstream(_file_name);
  }
}

整个过程在一个二进制文件中运行良好。但是,在使用DLL的可执行文件中调用了Logging<TARGET_DEBUG>::set_log_file(someFilePath.c_str());之后,我希望能够在DLL中使用Logging<TARGET_DEBUG>::log("some message");。最初,它不起作用,因为我没有使用__declspec(dllexport)导出类。然而,当我将适当的宏添加到日志类定义中(仅标题)时,我会收到一系列错误消息:

警告C4273:"sStream":dll链接不一致//为什么指针会出现这种情况?

错误C2491:"日志记录::sStream":不允许定义dllimport静态数据成员

应用程序中的其他各种类都可以顺利导出/导入,但这是我试图在二进制文件之间共享的唯一模板类。这不是一个我过于熟悉的领域,所以:我如何才能让这项工作如我所愿?请注意,EXE包括带有__declspec(dllimport)的Logging结构,带有__declspec(dllexport) 的DLL

您需要将显式模板实例化与__declspec修饰符结合使用。这将导致模板成员生成从DLL导出。它还将告诉访问模板成员的应用程序,应该导入而不是生成模板成员。

下面的代码进入DLL项目中的头文件

// Normal __declspec import/export stuff
// Define EXPORT_LOGGING in the preprocessor settings of your DLL project 
#ifdef EXPORT_LOGGING
#define LOG_EXPORT __declspec(dllexport)
#else
#define LOG_EXPORT __declspec(dllimport)
#endif
template <int TARGET>
struct LOG_EXPORT Logging
{
    static std::ostream * sOstream;
    static void log(const char * _txt)
    {
        // ... logging code ...
    }
    static void set_log_file(const char * _file_name)
    {
        sOstream = new std::ofstream(_file_name);
    }
};

下面的代码进入DLL项目中的.cpp文件

// static member for TARGET_DEBUG
std::ostream* Logging<TARGET_DEBUG>::sOstream = nullptr;
//  explicit template instantiation
template struct Logging<TARGET_DEBUG>;

最新更新