c++ 从另一个动态库分配未知的继承类

rsl1atfo  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(127)

我正在做一个小游戏引擎项目,我想做一个实体分配系统。
这个想法是这样的:引擎DLL是“不可改变的”,由我提供。开发者将能够编译游戏DLL自己与自定义实体类型。
每个实体都是从引擎的CBase类派生的。实体都有类名,当阅读Map时会使用这些类名。实体将使用这些类名“生成”。它基本上是该实体的别名。
但有个问题:
“衍生”实体的分配应该在引擎中完成。引擎应该能够调用基本函数,并且不能调用附加函数。
但是Engine并不从Game DLL导入这些类,所以我不能只使用new EntityClass
如何从其他DLL中分配未知类(从已知类派生)?是否有方法通过函数“传递类型”?
我之前的解决方法就像这样的伪代码:
发动机:

class DLLEXPORT CBase
{
  std::string className;

  virtual void Init();
  virtual void OtherMethod();
}

CBase* CreateNewEntity(const char* classname)
{
  CBase* newentity = static_cast<CBase*>(SERVER_DLL_GETNEWOBJECT(classname));
  newentity->Init();
  entitylist.addentity(newentity);
}

字符串
游戏DLL:

class DLLEXPORT CBaseEntity : public DLLIMPORT CBase
{
  //Called by engine
  virtual void Init() override;
  virtual void OtherFunction() override;

  //Inaccesible by engine
  virtual void AnotherFunction() override;
}

CBaseEntity* SERVER_DLL_GETNEWOBJECT(const char* classname)
{
  if (strcmp(className, "Entity_Weapon_Test") == 0)
  {
      return static_cast<CBaseEntity*>(new CTestWeapon);
  }
  else
      return nullptr;
}


SERVER_DLL_GETNEWOBDLL从游戏DLL导出,并导入到服务器DLL。它将是一个预定义的函数。
但是在这个解决方案中,分配是由游戏DLL完成的,而不是由引擎完成的。所以我不能使用它。

frebpwbc

frebpwbc1#

我会期待沿着这些线的东西:

#include <memory>
#include <string>
#include <functional>
#include <map>
#include <stdexcept>
#include <iostream>

// Declare an "interface" (abstract baseclass)
// this is the only knowledge your engine
// and client code will share
//
// But make sure client code compiles with an ABI
// compatible compiler!
//
class EntityItf
{
public:
    virtual ~EntityItf() = default;
    virtual void DoSomething() = 0;
};

using creation_function_t = std::function<std::unique_ptr<EntityItf>()>;

class /*dllexport */ EntityFactory
{
public:
    // Meyers singleton
    inline static EntityFactory& Instance()
    {
        static EntityFactory factory;
        return factory;
    }

    void RegisterCreationMethod(const std::string& entity_name, creation_function_t creation_function)
    {
        if ( m_factory_functions.find(entity_name) != m_factory_functions.end())
        {
            throw std::runtime_error{"An entity with that name has already been registered"};
        }

        m_factory_functions[entity_name] = creation_function;
    }

    std::unique_ptr<EntityItf> CreateEntity(const std::string& entity_name)
    {
        if ( m_factory_functions.find(entity_name) == m_factory_functions.end())
        {
            throw std::runtime_error{"Unknown entity name"};
        }

        return m_factory_functions[entity_name]();
    }

private:
    EntityFactory() = default;
    ~EntityFactory() = default;

    std::map<std::string,creation_function_t> m_factory_functions;
};

// Developer code

class MyEntity :
    public EntityItf
{
public:
    void DoSomething() override
    {
        std::cout << "Hello World!\n";
    }
};

int main()
{
    auto& factory = EntityFactory::Instance();
    factory.RegisterCreationMethod("MyEntity", []{ return std::make_unique<MyEntity>(); });

    auto my_entity = factory.CreateEntity("MyEntity");
    my_entity->DoSomething();

    return 0;
}

字符串

相关问题