在x64 DLL中强制名称修改

时间:2016-10-28 09:15:19

标签: c windows dll 64-bit name-mangling

我正在将32位应用程序移植到64位。该应用程序支持DLL的插件。不幸的是,每个插件需要具有的强制函数之一称为FreeLibrary,这当然与同名的kernel32 API冲突。我的插件API使用FreeLibrary名称的原因是该应用程序源自FreeLibrary与任何OS API不冲突的不同平台。

但是,即使在使用FreeLibrary的32位Windows上也不是问题,因为32位DLL使用名称修改,即该函数存储为_FreeLibrary,因此不会与{0}冲突kernel32 API。

在64位上,我现在有一个问题,因为64位似乎没有使用名称修改。在64位上,编译器创建一个名为FreeLibrary的符号,当然这与同名的kernel32 API冲突并拒绝链接,导致以下错误:

Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

kernel32.lib(KERNEL32.dll) : error LNK2005: FreeLibrary already defined in test.o
    Creating library test.lib and object test.exp
test.dll : fatal error LNK1169: one or more multiply defined symbols found

因此,我想知道是否有办法强制x64 DLL在32位上使用名称修改,以便我的DLL可以导出名为FreeLibrary的符号,而不会与{{1}发生任何冲突}}?

或者还有其他解决方案可以解决这个问题吗?

我看到的唯一解决方案是将kernel32重命名为与我的应用程序的x64版本不与OS API冲突的内容,但当然我希望避免这种情况,因为它会减少我的应用程序的插件API的一致性。如果可能,我希望在所有平台和架构中保留FreeLibrary名称。

有什么想法吗?我想如果在32位上有可能在DLL中使用保留名称如FreeLibrary那么应该有办法在64位上执行它,不应该在那里吗?但我不明白......

1 个答案:

答案 0 :(得分:0)

我不会试图说服编译器破坏函数的名称。那种方式就是疯狂。

为了澄清,您唯一的问题是链接插件DLL时的重复符号。应用程序本身不应该关心函数的命名,因为它将通过GetProcAddress收到的函数指针来调用插件入口点。

假设插件不需要调用kernel32.dll中实现的Windows API,您可以尝试从链接器命令中省略kernel32.dll。 (请参阅/NODEFAULTLIB选项。)如果kernel32.dll不是链接的一部分,则不应该发生冲突。

但是这不会起作用,因为命令行中的/MT意味着你依赖于C运行时库,而C运行时库依赖于某些kernel32.dll API。 (另外,您确定要将插件链接到静态运行时库而不是DLL版本吗?)

因此剩下的选项是更改函数的名称。这应该是微不足道的,因为无论如何都要移植。您甚至可以在编译插件时使用预处理器来破解名称,这样您就不需要更改源代码了:

cl /EHsc /c /DFreeLibrary=Plugin_FreeLibrary /Fotest.o test.c

然后更改应用中的GetProcAddress调用以查找Plugin_FreeLibrary而不是FreeLibrary,我认为这只发生在一个地方。