2013-07-08 51 views
1

我有一個記錄類,它可以簡化爲這樣的:如何使用跨越邊界的DLL靜態數據成員模板類的VC10

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:'sOstream':不一致的dll連接指針?

錯誤C2491:「記錄:: sOstream」:不準在應用

各種其他類出口/沒有問題進口dllimport的靜態數據成員的定義,但是這是唯一的模板類我試圖分享二進制文件。這不是我過分熟悉的領域:我如何根據需要進行這項工作?注意EXE包括與__declspec(dllimport)的記錄結構,與__declspec(dllexport)

回答

3

您需要結合使用顯式模板實例與__declspec修改的DLL文件。這將導致從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); 
    } 
}; 

下面的代碼進入一個.cpp文件在您的DLL項目

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

// explicit template instantiation 
template struct Logging<TARGET_DEBUG>; 
+0

偉大的工作,謝謝!我改變的只是在模板頭文件中定義了靜態成員和顯式實例,並由'#ifdef EXPORT_LOGGING'來保護,所以任何想要這個特性的項目都只需要包含頭文件就可以工作。我唯一剩下的問題是:這個解決方案是否可以使用多個使用相同頭文件的DLL?有沒有一種優雅的方式使這種解決方案可用於獨立的可執行文件,該文件不會鏈接到導出這些定義的DLL上? – Rollie

+0

是的,它可以處理多個模塊連接主DLL,無論它們是EXE還是DLL文件。你可以讓它和一些'#ifdef'一起工作,但是它的優雅是否在旁觀者眼中;)你可以將現有的'#ifdef'語句包裝在'#ifdef USE_IN_DLL'和'#else '定義'LOG_EXPORT'爲空。 –

相關問題