c++ - 模块化游戏引擎 : DLL circular dependencies

标签 c++ dll module directx game-engine

我想创建一个游戏引擎作为培训和投资组合项目,模块化方法听起来很有前途,但我在模块设计方面遇到了一些问题。

首先,我想创建低级模块,如渲染、应用程序、实用程序等,然后在 Terrain 等高级模块中使用它们。 所以依赖关系看起来像这样 Game<-Engine<-Terrain<-Rendering.

我想创建多个渲染“子模块”,如 Rendering.Direct3D11 和 Rendering.OpenGL。那就是我会有循环依赖的地方。子模块会使用 Rendering 接口(interface),Rendering 需要管理子模块,对吧? 游戏<-引擎<-地形<-渲染<-->渲染.Direct3D11

我或许可以创建一个像 RenderingInterfaces 这样的模块并打破循环依赖,但这似乎是一个棘手的解决方法。我打算多次使用“子模块设计”,例如: 游戏<-引擎<-应用程序<-->Application.Windows

子模块设计丑吗?有没有办法使用没有循环依赖的子模块设计?

最佳答案

你可以抽象地解决这个问题。假设您有三个动态库:Game.dllRenderer.dllSubRenderer.dll

渲染器界面可能看起来像这样(简化):

// Renderer.h
class SubRenderer
{
public:
     virtual ~SubRenderer() {}
     virtual void render() = 0;
};

class API Renderer
{
public:
     explicit Renderer(SubRenderer* sub_renderer);
     void render();

private:
     SubRenderer* sub_renderer;
};

你可以把它放在 Renderer.h 或类似的东西中,Renderer 构造函数和 render 方法可以在 Renderer.cpp 中实现> 您将其包含在输出 Renderer.dll 的项目中。

现在在 SubRenderer.dll 中,您可能有这样一个函数:

// SubRenderer.h
class SubRenderer;
API SubRenderer* create_opengl_renderer();

这可以在 SubRenderer.cpp 中实现,它被编译/链接到输出 `SubRenderer.dll。它可能看起来像这样:

// SubRenderer.cpp
#include "SubRenderer.h"
#include <Renderer.h>

class OpenGlRenderer: public SubRenderer
{
public:
    virtual void render() override {...}
};

SubRenderer* create_opengl_renderer()
{
    return new OpenGlRenderer;
}

最后但同样重要的是,在 Game.dll 的某些源文件中,您可以在某些 Game.cpp 中执行类似的操作:

// Game.cpp
#include <Renderer.h>
#include <SubRenderer.h>

int main()
{
    SubRenderer* opengl_renderer = create_opengl_renderer();
    Renderer renderer(opengl_renderer);
    renderer.render(); // render a frame
    ...
    delete opengl_renderer;
}

...当然希望有符合 RAII 的更安全的设计。

对于这种系统,您有这些 header 依赖项:

`Game.cpp->Renderer.h`
`Game.cpp->SubRenderer.h`
`SubRenderer.cpp->Renderer.h`

在模块依赖方面:

`Game.dll->Renderer.dll`
`Game.dll->SubRenderer.dll`

就是这样——任何地方都没有循环依赖。 Game.dll依赖于Renderer.dllSubRenderer.dll,但是Renderer.dllSubRenderer .dll 完全相互独立。

这是可行的,因为这个 Renderer 可以使用给定其虚拟接口(interface)的 SubRenderer 而不知道它到底是什么(因此不需要依赖于具体类型的“子渲染器” ').

您可以将 Renderer.h 放在可以从所有三个项目集中访问的位置,这些项目具有共同的包含路径(例如:在 SDK 目录中)。无需复制。

关于c++ - 模块化游戏引擎 : DLL circular dependencies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33630692/

相关文章:

c++ - 如何使用 #error 指令 - C++

从 C 调用的 C++ 共享库

c++ - 即使引用计数不为零,动态加载的 DLL 也可以被 Windows 卸载,如何处理?

c++ - 关于优化不会出现在 EXE 中的 DLL 有什么注意事项吗?

python - GAE - 包括外部 python 模块而不将它们添加到存储库?

javascript - ES6 中的惰性模块加载是如何工作的

c++ - 输入不是数字时输出错误。 C++

c++设计模式以避免复制和向下转换

c++ - 为什么 rundll 缺少条目?

javascript - 为什么共享模块导入不会失败?