プラグイン アーキテクチャをサポートする必要があるアプリケーションに取り組んでいます。これは初めてのことなので、どうすればいいのかよくわかりません。
How to create some class from dll(constructor in dll)?(с++)は、完全に仮想関数で構成されるクラスを作成し、DLL にそれをカスタム クラスに実装させ、そのカスタム オブジェクトをGetPluginObject()
メソッドまたはなど。ただし、C++ DLL プラグイン インターフェイスは、それだけでは不十分であり、適切な (複数のコンパイラ間で互換性のある) アプローチには次のものが必要であると述べています。
- 基本データ型のみ使用可能
- プラグイン DLL が実装するインターフェイスを適切に識別できるように、COM の QueryInterface のようなものを公開する必要があります。
- 何らかの形式の参照カウントが必要です
- すべてのメソッドは stdcall としてマークすることが望ましい
- 構造体には固定アラインメントを指定する必要があります
プラグインに必要なことは非常に単純です。必要なのは、1 つの関数から返される構造体の 1 つの配列だけです。
struct InternalCommand
{
int commandValue;
std::wstring commandName;
std::wstring commandHandlerFunctionName; //I'm planning on using GetProcAddress with the provided function name to get the individual command handler
}
std::vector<InternalCommand> GetEmergeInternalCommands();
上記のリストの制限と要件を考慮し、このプロジェクトの別のインターフェイスをテンプレートとして使用すると、次の方法でこれを定義する必要があるようです。
#define MAX_LINE_LENGTH 4096
#ifdef __GNUC__
#define ALIGNOF(type) __alignof__(type)
#else
#define ALIGNOF(type) __alignof(type)
#endif
#ifdef __GNUC__
#define ALIGNED(size) __attribute__((aligned (size)))
#else
#define ALIGNED(size) __declspec(align(size))
#endif
#include <windows.h>
// {b78285af-c62f-4cff-9e15-f790a4a219ee}
const IID IID_IEmergeInternalCommand = {0xB78285AF, 0xC62F, 0x4CFF, {0x9E, 0x15, 0xF7, 0x90, 0xA4, 0xA2, 0x19, 0xEE}};
#ifdef __cplusplus
extern "C"
{
#endif
struct ALIGNED((ALIGNOF(int) + ALIGNOF(wchar_t) + ALIGNOF(wchar_t))) EmergeInternalCommandInformation
{
int commandValue;
wchar_t commandName[MAX_LINE_LENGTH];
wchar_t commandHandlerFunctionName[MAX_LINE_LENGTH];
};
#undef INTERFACE
#define INTERFACE IEmergeInternalCommandProvider
DECLARE_INTERFACE_(IEmergeInternalCommandProvider, IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID, LPVOID*) PURE;
STDMETHOD_(ULONG, AddRef)(THIS) PURE;
STDMETHOD_(ULONG, Release)(THIS) PURE;
STDMETHOD_(int, GetEmergeInternalCommandCount)(THIS) PURE;
STDMETHOD_(EmergeInternalCommandInformation, GetEmergeInternalCommandInformation)(THIS_ int) PURE;
};
#undef INTERFACE
typedef IEmergeInternalCommandProvider* LPEMERGEINTERNALCOMMANDPROVIDER;
#ifdef __cplusplus
}
#endif
次に、ホスト側では、プラグイン DLL で を使用GetProcAddress
して DLL を呼び出し、QueryInterface
ポインタQueryInterface
リターンを使用してプラグインを操作します。
ただし、これはやり過ぎで醜いように思えます。たとえば、std::vector を適切に入出力できるとは思えないため、プラグインのコマンドを 1 つずつループできるように、単一項目の returnと total-count 関数を使用して行き詰まっています。 . ルールを破ることなく構造体配列を戻り値として安全に取得できる別の方法はありますか?GetEmergeInternalCommandInformation()
GetEmergeInternalCommandCount()
wchar_t
また、配列を持つという点 (単一wchar_t
の s に制限されていますか?) とアライメント値の両方に関して、構造体を正しく定義したかどうかはまったくわかりません。
また、プラグイン DLL がこれをどのように実装するのか、完全にはわかりません。#include
インターフェイス定義ヘッダーが必要で、インターフェイスから継承するクラスを作成するだけだと思いますよね?
#include "EmergeInternalCommandInterface.h"
class EmergeInternalCommands : public IEmergeInternalCommandProvider
//class definition goes here
また、このインターフェイスを COM に登録する必要があるのか、それとも単に使用できるのかについてもわかりません。テンプレートとして使用したインターフェイスは本格的な COM インターフェイスであり、そのように登録されていますが、基本的なプラグイン システムに高度なものが必要かどうかはわかりません。
そして最後になりましたが、間違いなく重要なことです-私はこの方法を必要以上に複雑にしていますか?