1

次のように簡略化できる 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>::log("some message");を呼び出した後、DLL 内で使用できるようにしたいです。Logging<TARGET_DEBUG>::set_log_file(someFilePath.c_str());もともと、でクラスをエクスポートしていなかったため、機能しませんでした__declspec(dllexport)。ただし、適切なマクロをロギング クラス定義 (ヘッダーのみ) に追加すると、一連のエラー メッセージが表示されます。

警告 C4273: 'sOstream' : dll リンケージに一貫性がありません // ポインタに対してこれが発生するのはなぜですか?

エラー C2491: 'Logging::sOstream': dllimport 静的データ メンバーの定義は許可されていません

アプリケーションの他のさまざまなクラスは問題なくエクスポート/インポートされますが、バイナリ間で共有しようとしているテンプレート化されたクラスはこれだけです。それは私があまりよく知っている分野ではないので、どうすればこれを希望どおりに機能させることができますか? EXE には、 を持つロギング構造体、 を持つ__declspec(dllimport)DLL が含まれていることに注意してください。__declspec(dllexport)

4

1 に答える 1

3

__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);
    }
};

以下のコード.cppは、DLL プロジェクトのファイルに入ります。

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

//  explicit template instantiation
template struct Logging<TARGET_DEBUG>;
于 2013-07-08T22:47:39.933 に答える