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实例包含某种(多)映射 from std::stringto UserObjectFactory

myname可以初始化为一些唯一生成的字符串而不是typeid(UserClass).name(),以避免冲突。

如果您只需要每个用户类的单个对象,则可以UserObjectFactory创建一个实例UserClass并注册它。

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

这种设计是否满足您的需求?

于 2011-07-05T13:50:08.520 回答