【发布时间】:2021-06-03 22:06:58
【问题描述】:
我有一个相当简单的插件系统,可以在运行时加载和重新加载 dll。没有任何涉及的静态链接。 .exe 仅包含加载 dll 所需的代码。它目前通过使用 LoadLibrary/GetProcAddress/FreeLibrary 函数在 Windows 下执行此操作。 (在 VisualStudio 中)没有设置额外的库目录、项目引用或库。
然而,我正在做的是包含一些来自 dll 项目的头文件,我稍后会动态加载这些头文件(以防万一)。现在我知道我可能应该只使用 GetProcAddress 查询的接口函数来调用 dll,但这是我第一次这样做,所以我只是在搞清楚。
现在假设我得到了一个 CreateWindow 函数的函数指针,如下所示:
void LoadPlugin(PlatformPlugin* plugin)
{
plugin->Handle = LoadLibrary(plugin->PLUGIN_FILE_TEMP);
plugin->CreateWindow = (PLUGIN_PLATFORM_CreateWindow)GetProcAddress(plugin->Handle, "CreateWindow");
}
CreateWindow 函数返回一个指向 Window 对象的指针,该对象主要包含虚函数,并由特定于平台的 Window 类(如 WindowsWindow)继承:
class Window
{
public:
virtual unsigned int GetWidth() const = 0;
virtual unsigned int GetHeight() const = 0;
};
class WindowsWindow : public Window
{
public:
virtual unsigned int GetWidth() const override;
virtual unsigned int GetHeight() const override;
};
当然,还有一个包含定义的 .cpp 文件。 '问题'来了:当调用 CreateWindow 时,我得到了有效的指针,当在它上面调用 GetWidth 时,我也得到了正确的结果。但您可能已经注意到,我从未导出任何 Window 类或函数。据我了解,我不应该调用 GetWidth,但我可以。 Dependencywalker 证实了这一点,并将 CreateWindow 作为导出函数显示给我。 反正我怎么称呼它?包含的头文件只是为编译器提供了理论上调用函数所需的信息,但由于头文件实际上并不包含函数实现,链接器如何知道我的函数的地址?
【问题讨论】:
标签: c++ dll loadlibrary hot-reload