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

rsl1atfo  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(147)

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

  1. class DLLEXPORT CBase
  2. {
  3. std::string className;
  4. virtual void Init();
  5. virtual void OtherMethod();
  6. }
  7. CBase* CreateNewEntity(const char* classname)
  8. {
  9. CBase* newentity = static_cast<CBase*>(SERVER_DLL_GETNEWOBJECT(classname));
  10. newentity->Init();
  11. entitylist.addentity(newentity);
  12. }

字符串
游戏DLL:

  1. class DLLEXPORT CBaseEntity : public DLLIMPORT CBase
  2. {
  3. //Called by engine
  4. virtual void Init() override;
  5. virtual void OtherFunction() override;
  6. //Inaccesible by engine
  7. virtual void AnotherFunction() override;
  8. }
  9. CBaseEntity* SERVER_DLL_GETNEWOBJECT(const char* classname)
  10. {
  11. if (strcmp(className, "Entity_Weapon_Test") == 0)
  12. {
  13. return static_cast<CBaseEntity*>(new CTestWeapon);
  14. }
  15. else
  16. return nullptr;
  17. }


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

frebpwbc

frebpwbc1#

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

  1. #include <memory>
  2. #include <string>
  3. #include <functional>
  4. #include <map>
  5. #include <stdexcept>
  6. #include <iostream>
  7. // Declare an "interface" (abstract baseclass)
  8. // this is the only knowledge your engine
  9. // and client code will share
  10. //
  11. // But make sure client code compiles with an ABI
  12. // compatible compiler!
  13. //
  14. class EntityItf
  15. {
  16. public:
  17. virtual ~EntityItf() = default;
  18. virtual void DoSomething() = 0;
  19. };
  20. using creation_function_t = std::function<std::unique_ptr<EntityItf>()>;
  21. class /*dllexport */ EntityFactory
  22. {
  23. public:
  24. // Meyers singleton
  25. inline static EntityFactory& Instance()
  26. {
  27. static EntityFactory factory;
  28. return factory;
  29. }
  30. void RegisterCreationMethod(const std::string& entity_name, creation_function_t creation_function)
  31. {
  32. if ( m_factory_functions.find(entity_name) != m_factory_functions.end())
  33. {
  34. throw std::runtime_error{"An entity with that name has already been registered"};
  35. }
  36. m_factory_functions[entity_name] = creation_function;
  37. }
  38. std::unique_ptr<EntityItf> CreateEntity(const std::string& entity_name)
  39. {
  40. if ( m_factory_functions.find(entity_name) == m_factory_functions.end())
  41. {
  42. throw std::runtime_error{"Unknown entity name"};
  43. }
  44. return m_factory_functions[entity_name]();
  45. }
  46. private:
  47. EntityFactory() = default;
  48. ~EntityFactory() = default;
  49. std::map<std::string,creation_function_t> m_factory_functions;
  50. };
  51. // Developer code
  52. class MyEntity :
  53. public EntityItf
  54. {
  55. public:
  56. void DoSomething() override
  57. {
  58. std::cout << "Hello World!\n";
  59. }
  60. };
  61. int main()
  62. {
  63. auto& factory = EntityFactory::Instance();
  64. factory.RegisterCreationMethod("MyEntity", []{ return std::make_unique<MyEntity>(); });
  65. auto my_entity = factory.CreateEntity("MyEntity");
  66. my_entity->DoSomething();
  67. return 0;
  68. }

字符串

展开查看全部

相关问题