1

私はC++フレームワークを書く際に問題があり、ユーザーはそれを使用できるよりもオーバーヘッドが少ないはずです。ユーザーは、フレームワークの BaseClass から派生したクラスを含む共有ライブラリを作成し、その派生クラスのインスタンスを返すために extern "C" createInstance() メソッドを実装することで、自分の作業をフレームワークに公開できます。したがって、フレームワークは、dlsym() を使用して共有ライブラリを介して createInstance-Method を呼び出すことにより、ユーザー クラスにアクセスできます。

class BaseClass{}
class UserClass : public BaseClass{}

extern "C"{  
   BaseClass* UserXcreateInstance(){
    return new UserClass();
   }                        
}

フレームワーク:

typedef BaseClass* (*CreateInstance) ();
void* handle;
CreateInstance createInstance;
handle = dlopen( "libUserLibrary.so", RTLD_LAZY | RTLD_GLOBAL );
createInstance = reinterpret_cast <CreateInstance*> dlsym( handle, "UserXcreateInstance" );
BaseClass* userX = createInstance();

私の質問: ユーザーが考える必要がないように、各ユーザー ライブラリで冗長な UserXcreateInstance() メソッドを生成することは可能ですか?

テンプレート+マクロで可能だと思っていましたが、これを行う方法はまだ見つかりません...

別のアプローチとして、dlsym と適切な名前マングリングを介して任意のユーザー クラスのコンストラクターを直接呼び出すことを考えていました。(構成ファイルから名前空間とクラス名を知っています)しかし、これが適切な解決策だとは思いません。特に、コンストラクター呼び出しは通常の関数呼び出しと同じではありません...しかし非常に興味深い...

4

2 に答える 2

4

ユーザーの一部ごとにコーディングせずにこれを自動的に作成する方法を想像することはできません。おそらくマクロを使用して、それを単純化する方法を想像することができます。

#define OBJECT_CREATOR(X) \
    extern "C" {          \
         BaseClass *UserXCreateInstance() {\
             return new X(); \
         }\
    }

そして、ユーザーは自分のcppファイルを置く必要があります。

OBJECT_CREATOR(UserClass);
于 2011-07-05T11:51:46.957 に答える
3

経由でユーザー関数を呼び出すことはdlsym絶対的な要件ではないと仮定します。

CRTPを使用すると、目的を簡単に達成できます。次に、静的ヘルパー オブジェクトのコンストラクターが、関連データを中央リポジトリに登録します。次のようになります。

template <typename UserClass>
class BaseClass
{
  private:
    class UserObjectFactory
    {
      UserObjectFactory()
      {
        std::string myname = typeid(UserClass).name();
        CentralObjectFactory::instance()->register(this, myname);
      }
      BaseClass* XUserCreateInstance()
      {
        return new UserClass;
      }            
    };
    static UserObjectFactory factory; 
};

ユーザー コードは単純です。

class MyClass : public BaseClass<MyClass>
{
  // whatever
};

おそらく、インスタンスには からへCentralObjectFactoryの何らかの (マルチ) マップが含まれています。std::stringUserObjectFactory

mynametypeid(UserClass).name()衝突を避けるために、の代わりに一意に生成された文字列に初期化できます。

必要なのは各ユーザーのクラスの単一のオブジェクトだけである場合は、代わりにUserObjectFactoryインスタンスを作成してUserClass登録することができます。

   std::string myname = typeid(UserClass).name();
   CentralObjectRepository::instance()->register(XUserCreateInstance(), myname);

このデザインはあなたのニーズを満たしていますか?

于 2011-07-05T13:50:08.520 に答える