如何使用visual studio构建可替换的dll

How do you build replaceable DLLs with visual studio?

本文关键字:可替换 dll 构建 studio 何使用 visual      更新时间:2023-10-16

我想将游戏的某些扩展构建为DLL,以便我可以重新编译扩展并替换DLL,而无需重建整个游戏。我该怎么做呢?

我在某处读到,每个新版本的DLL都必须与旧版本"二进制兼容"。dll编译与visual studio二进制兼容默认情况下,只要我不改变函数名称?

您必须做的不仅仅是保持函数名称相同。您必须确保的是所谓的应用程序二进制接口,或ABI,兼容性。

除了符号名,还有很多东西需要处理。例如,您必须做一些事情,例如保持跨DLL边界传递的数据结构的大小相同,并且编译器必须将在模块中定义但在其外部访问的任何类成员放置在相同的相对位置。这在很大程度上取决于编译器的ABI。Microsoft编译器有一个坏习惯,即不兼容不同版本的ABI,而其他一些编译器在兼容方面做得稍微努力一些。但请记住,它需要的不仅仅是使用相同的编译器。

您可能需要仔细阅读如何在您的环境中维护ABI兼容性,因为它可能涉及比这里列出的更多的细节,并且有很多出错的方法。这里有一篇关于它的短文。可能有更好的专门针对MSVC编译器的

如果您从DLL中导出类,如果您更改编译器的版本,您将破坏兼容性。为了解决这个问题,请这样做。

使类接口如下:

class EXPORT_IMPORT_MACROS IMyApi{
public:
 virtual void doSomething( IOtherApi* api ) = 0;
 virtual void doSomething2( IOtherApi2* api ) = 0;
};

并从dll中导出它们。它会给你一个独立于dll实现的头文件,也可以导出,这意味着它不会在不同版本的运行时库中产生任何问题。你也可以看看COM技术

一种方法是重新编译dll。只要编译器(Visual Studio)的版本不变,dll是兼容的。否则,您将不得不查看Visual Studio版本之间的兼容性手册。

另一种方法是通过使用LoadLibrary函数动态加载dll,然后使用GetProcAddress函数来检索你想调用的函数的地址。

如果您使用后者,您可以使用任何编译器,只要您正确地使用dllexport导出函数并使用dllimport导入它们。