我正在将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位上执行它,不应该在那里吗?但我不明白......
答案 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
,我认为这只发生在一个地方。