0

私はVS2010を使用しており、MVCアプリケーションを設計しています。

ソリューションに「プロジェクト1」と「プロジェクト2」があるとします。この順序でコンパイルする必要があります。P1はDLLにコンパイルされ、P2はDLLを動的に使用するExeファイルにコンパイルされます。P2はビューインターフェイスを宣言します。どちらのプロジェクトにも、インターフェイスを実装するビュークラス(純粋仮想メソッドを持つクラス)があります。

ここでの問題は、リンカがこの外部シンボルを解決できないと言うため、インターフェイスのヘッダーファイルをP1にインクルードできないことです。もちろん、これは正しいです。後でP2でコンパイルされるからです。

つまり、P2のインクルードフォルダーをP1に追加し、ヘッダーファイルの代わりにinterface.cppをP1にインクルードしました。

それは動作しますが、私はこれが私がすることになっていることではないと思います。それともそうではありませんか?インターフェイスは明らかに2回コンパイルされ、各プロジェクトに1回ずつコンパイルされます。

インターフェイスをP1に移動したくないので、問題を解決できます。ただ仮定してください、私はそれを望んでいません。

ご入力いただきありがとうございます。

編集:コードスニペット:

Project1:

View1.hpp // nothing special

View1.cpp:

#include ViewInterface.cpp
View1::View1(int x) : ViewInterface(int x)

Project2:

ViewInterface.hpp:

#ifdef EXP
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif

class ViewInterface : SomeOtherClass, AnotherClass
{
  virtual void DECLDIR show(void) const = 0;
  virtual void DECLDIR hide(void) const = 0;
}

ViewInterface.cpp:

ViewInterface::ViewInterface(int x) : SomeOtherClass(int x), AnotherClass(int x)

View2.hpp // nothing special

View2.cpp:
#define EXP
#include ViewInterface.h

View2::View2(int x) : ViewInterface(int x)
4

2 に答える 2

1

実行可能ファイルがDLLのクラスを使用するには、それらが正しくエクスポートされていることを確認する必要があります。DLLをコンパイルするときは、クラスを。__declspec(dllexport)でマークし、実行可能ファイルをコンパイルするときは、代わりに。でクラスをマークし__declspec(dllimport)ます。通常、これは次のようなマクロで実行されます。

// In your DLL's header file
#ifdef COMPILING_MY_DLL
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT __declspec(dllimport)
#endif

class MY_EXPORT MyClass
{
    ...
};

次に、DLLプロジェクトでのみCOMPILING_MY_DLL、マクロを定義します。

于 2012-10-24T21:40:51.507 に答える
0

インターフェイスをP1に移動したくないので、問題を解決できます。ただ仮定してください、私はそれを望んでいません。

次に、それを3番目のエンティティに移動します。

あなたはあなたにとって何がより重要であるかを決定しなければなりません。クリーンなソリューションが必要な場合は、インターフェイス定義をDLL(P1)に移動するか、DLLとEXEの両方が使用できるものに移動します。これを「P0」と呼びましょう。P0は、コンパイルされたものである必要はありません。インラインで定義されたすべてのものを含む独自のディレクトリ内の単純なヘッダーファイルで問題ありません。私の好みの選択は、P0をDLLにすることです。

それが唯一のクリーンな解決策です。以下の「解決策」は、完全を期すために私が説明する単なるハックです。


本当に「ダーティ」なソリューションが必要な場合は、同じことを行いますが、唯一の違いは、インターフェイスを定義するヘッダーファイルをapplication-source-folderに残すことです。

そして、それを非常に汚くしたい場合は、提案したようにDLLをビルドするときに.cppファイルを含めます。それも機能します...それは本当にうんざりです。

もちろん、あなたはいくつかのことに注意する必要があります。たとえば、「インターフェイス」には静的データメンバーが含まれていてはならず、「インターフェイス」内の関数にはローカル静的関数が含まれていてはなりません。その場合、これらの静的変数は2回インスタンス化されます。1回はDLLで、もう1回はEXEでインスタンス化されます。また、すべてのコードが両方のプロジェクトにコンパイルされるため、何かを変更する場合は、両方のプロジェクトを再コンパイルする必要があります。(DLLとEXEで重複しているコードは、同じコードからコンパイルされている限り問題ありません。)

もちろん、これらの制限は、「P0=単なるヘッダーファイル」ソリューションを選択した場合にも当てはまります。


そして最後に、本当にひどい非常に汚い解決策があります:EXEにインターフェースを実装し、EXEからdllexportし、DLLにdllimportします(そうです、それは可能です!)。欠点は、EXEのインポートライブラリのみをビルドする特別なEXEビルドを実行する必要があることです(これは、DLLのインポートライブラリがなくても実行できます)。次に、EXEのインポートライブラリを使用してDLLをビルドし、DLLのインポートライブラリを使用してEXE自体をビルドできます。そうすれば、「インターフェイス」に静的データメンバーを含めることもでき、コードのみを変更した場合(つまり、ヘッダーファイルを変更しない場合)は、EXEを再コンパイルするだけで済みます。

于 2012-10-24T22:24:30.253 に答える