マネージドC ++ - 設定ファイルに基づいて異なるDLLを読み込みます
-
21-08-2019 - |
質問
私は現在、複数のクライアントのために同様の目的を果たすだろうアプリケーションを書いて、それはそれがフィードされたデータを処理する方法に適応を必要としています。本質的には同じ目的を果たしますが、完全に異なる方法でデータを配るされます。
だから私はこのようprodeedことにしました: すべての方法の一般的な機能を保持し、異なるエンジンが同じように反応することを確実にデフォルトのインターフェースを提示する一般的なエンジンライブラリを-make。 機能の各方法のため-write特定のエンジン....それぞれが独自の.dllにコンパイルされます。
私のプロジェクトは、いくつかのように見ているとライブラリの束となってしまいますので。 project_engine_base.dll project_engine_way1.dll project_engine_way2.dll
今、私たちは、ユーザの嗜好に使用する設定ファイルで、我々は、使用するエンジンエンジン部が決めることができるだろうようにます:
[ENGINE]
Way1
だから、どこかのコードでは、我々がやりたいだろう。
If (this->M_ENGINE == "Way1")
//load dll for way1
Else If (this->M_ENGINE == "Way2")
//load dll for way2
Else
//no engines selected...tell user to modify settings and restart application
質問は...どのように私は私のDLL(s)はこのようにインポートされますか?それも可能ですか?私は、機能の類似した方法を達成する方法についていくつかの提案を得ることができない場合は?
私はちょうど開始時にすべてのDLLをインポートし、ただ、使用するエンジンを選択でき承知していますが、アイデアは、私は何もして、廃棄物資源のためにあまりにも多くのエンジンをインポートしたくなかったということでしたし、私たちは」didnのtは、お客様にこれらのdllのすべてを出荷する必要がありますする必要。一つの顧客は、別の異なるものを使用しますつのエンジンを使用します。当社の顧客の中には、それゆえ、おそらく、私がこれを外部化し、ユーザーの皆様は、エンジンの切り替え用の設定ファイルを使用できるようにしたかった理由を複数使用します。
任意のアイデア?
編集: ただ、彼らは、実行時に動的にロードされ、すべてのプロジェクトで参照されていない場合は、私のエンジンのそれぞれが同じインターフェイスを提示するにもかかわらず、私のプロジェクトがコンパイルされないということに気づきました。だから私は、私はしていない選択肢を持っていませんが、私のプロジェクトでそれらのすべてを含めるように?
また、彼らはすべて私の顧客に出荷する必要があることを意味します。構成の設定は、私は私のエンジンメンバーを初期化するために使用するクラスを指示します。
または
私は、これらのエンジンのそれぞれが同じ名前にコンパイルする可能性があります。唯一の私のメインのプロジェクトに1つのDLLをインポートし、その特定のエンジンはすべての時間を使用することでしょう。それは、自分の複数のクライアントのために私たちのアプリケーションを使用することができない私の顧客をレンダリングします。彼らは手動でDLLを切り替えるために喜んでいた場合を除きます。 のウエッの
任意の提案ですか?
EDIT#2: 私のオプションを見て、この時点で、私はまた、ジュストユーザーが選んだようにする一つの大きなベースエンジンを含むDLLだけでなく、すべての子のものと私の設定を作ることができます。代わりに、複数のDLLを参照すると、それらすべてを出荷します。ただ、一つの巨大な1船/参照1つだけを持っています。私はこのあまり好きではないよどちらかではなくそこにニーズに合わせただ一つまたは二つの小さなものの私の顧客のすべてに一つの大きなDLLを出荷する手段として。これはまだ私も作ってみた最適なソリューションです。
私はまだ私の元の質問へのより良い提案や答えを探しています。 おかげます。
解決 2
私が来たソリューションは、次のされます:
Engine_Base^ engine_for_app;
Assembly^ SampleAssembly;
Type^ engineType;
if (this->M_ENGINE == "A")
{
SampleAssembly = Assembly::LoadFrom("path\\Engine_A.dll");
engineType = SampleAssembly->GetType("Engine_A");
engine_for_app = static_cast<Engine_Base^>(Activator::CreateInstance(engineType, param1, param2));
}
else
{
SampleAssembly = Assembly::LoadFrom("path\\Engine_B.dll");
engineType = SampleAssembly->GetType("Engine_B");
engine_for_app = static_cast<Engine_Base^>(Activator::CreateInstance(engineType, param1, param2, param3, param4));
}
私はダニエルと彼の答えで行われたコメントからの回答を使用していました。いくつかの余分な研究の後、私はLoadFromメソッドに出くわします。
他のヒント
のLoadLibrary <各エンジンのために別々のDLLを使用し、使用/>設定に基づいて特定のエンジンをロードする。メインプロジェクトで
すべてのエンジンから派生し、このインターフェイスは、あなたのメインプロジェクトのaswellに使用されるいくつかの共通のヘッダファイルでのエンジンインタフェースを持っています。
これは、次のようになります。
// this should be an abstract class
class engine {
public:
virtual void func1() = 0;
virtual void func2() = 0;
...
};
それぞれ異なるエンジンの実装では、DLLから関数をエクスポートこのような何かます:
// might aswell use auto_ptr here
engine* getEngine() { return new EngineImplementationNumberOne(); }
これであなたの主なプロジェクトで、単にあなたがLoadLibrary関数を使用してに興味があるDLLと、その後のGetProcAddress getEngine機能をロードします。
string dllname;
if (this->M_ENGINE == "Way1")
dllname = "dllname1.dll";
else if (this->M_ENGINE == "Way2")
dllname = "dllname2.dll";
else
throw configuration_error();
HMODULE h = LoadLibraryA(dllname.c_str());
typedef engine* (*TCreateEngine)();
TCreateEngine func = (TCreateEngine)GetProcAddress(h, "getEngine");
engine* e = func();
あなたもエラーをチェックすることを忘れないでください、あなたのDLL内のDEFファイルやEXTERN「C」を使用することができますいずれかのように、エクスポートされた関数の名前はおそらく、マングルされます。