2012-01-12 12 views
1

ここでは、プラグインフレームワークのための私が検討しているシナリオを示します。XMLファイルから関数宣言を動的に構築できますか?

サードパーティのプラグイン開発者は、既知のエントリポイントと任意のパラメータを持つDLLを設計します。また、XMLファイル内のエントリポイントとパラメータの詳細を提供し、プラグインが呼び出されたときに自分のプログラムによって呼び出されるデータを提供します。彼らはXMLで拡張可能な変数のセットを使用することができます。私のプログラムは拡張し、指定したパラメータを使ってそれらに戻します。

私が知っているのは、Win32ではLoadLibrary/GetProcAddressを使用して、定義した関数を保持することができます。私があまり明確でないのは、関数呼び出しを呼び出すために使用できる定義済みのパラメータから関数仕様を動的に生成できるかどうかです。これが可能なら誰でも知っていますか?

答えて

1

は、単にプラグインはのシンプルなインターフェイスを受け入れるようにすることですそれらを渡す、例えば

typedef struct 
{ 
    int a; 
    float b; 
    double c; 
    wchar_t * d; 
} test1; 

私にこのメッセージが届くと、バッファを使用する前にサイズをチェックして、XMLと構造が一致することを確認できます。

私はXMLを解析するように、私は動的にオブジェクトを作成するためのテンプレートメソッドでこのクラスを使用します。

class DynamicStructure 
{ 
public: 

    template <typename T> 
    void addField(const T & field) 
    { 
     m_mapPtrSize.push_back(std::make_pair(reinterpret_cast<const LPARAM>(&field), sizeof(T))); 
    } 

    DWORD getSize() 
    { 
     // 
     // Work out the combined size of all the fields 
     DWORD sSize = 0; 
     for (auto it = m_mapPtrSize.cbegin(); it != m_mapPtrSize.cend(); it++) 
     { 
      sSize += it->second; 
     } 

     return sSize; 
    } 

    LPARAM getBuffer() 
    { 
     // Create a buffer big enough for all the fields 
     // 
     LPARAM pBuf = reinterpret_cast<LPARAM> (new (std::nothrow) BYTE[getSize()]); 

     if (pBuf == NULL) 
      return NULL; 

     DWORD offset = 0; 
     for (auto it = m_mapPtrSize.cbegin(); it != m_mapPtrSize.cend(); it++) 
     { 
      // Copy the fields one at a time, offsetting into the buffer 
      // 
      memcpy((void*) (pBuf + offset), (const void*) it->first, it->second); 
      offset += it->second; 
     } 

     return pBuf; 
    } 

protected: 
private: 
    std::vector<std::pair<const LPARAM, DWORD>> m_mapPtrSize; 
}; 

これは私がXMLを解析として、私は以下の動作の種類を実行することができます:

DynamicStructure dynStruct; 
int a = 1; 
float b = 2.3f; 
double c = 3.5; 
wchar_t * d = L"bob"; 

dynStruct.addField(a); 
dynStruct.addField(b); 
dynStruct.addField(c); 
dynStruct.addField(d); 

// Test - does the dymanic structure match the user's structure? 
LPARAM pBuf = dynStruct.getBuffer(); 
test1 * pTest1 = (test1 *) pBuf; 

std::wcout << pTest1->a << " " << pTest1->b << " " << pTest1->c << " " << pTest1->d << std::endl; 

これは完璧ではなく、ちょっと古い学校ですが、少なくともシンプルであり、妥当なレベルの安全性を提供します。

0

実行時に関数をビルドすることはできません。そのため、テンプレートメタプログラミングのようなコンパイル時オプションが残っています。

1

C++はリフレクションをサポートしていません。

しかし、pococapsuleライブラリを使用することで(ある程度まで)可能です。


This articleは、プラグインフレームワークの構築方法を詳しく説明しています。ユーザーがXMLでそれらのパラメータを指定して、彼らは私を期待する構造を定義することができるようになる

DWORD func (LPARAM pBuf, DWORD size); 

この:私が行うことを決めた何

+0

パラメータを知っていれば、関数を体系的に呼び出すためには、完全リフレクションAPIが必要であるとは思いませんでした。結局のところ、理論的には呼び出し規約(私が行っていること)を知っていれば、アセンブラで行うのは "簡単"だと思います。標準のC++でこれを行う良い方法があるかどうかは不思議です。私はちょうどボイドスタイルの関数をたくさん使うことができ、私が必要としていたものを選んでポインタを戻す必要があったと思うが、これはやっかいなことだ。 – Benj

+0

@Benjいいえ、あなたは完全なリアクションは必要ありません。私はその質問を誤解しているかもしれません。この標準では、ライブラリをロードしてそのシンボル(プラットフォームに依存します)を使用する方法は記述されていません。そのためには、キャストする必要があります。なぜなら、あなたはc関数にしかアクセスできないからです。 –

+0

@Benjあなたが求めたのは、超複雑な問題です。私はフレームワークの良いプラグインを構築するのに役立つ記事をリンクしました。 –

関連する問題