在x64 DLL中强制名称修改
我正在将32位应用程序移植到64位。 该应用程序支持DLL的插件。 不幸的是,每个插件需要具有的强制函数之一称为FreeLibrary
,它当然与同名的kernel32
API冲突。 我的插件API使用FreeLibrary
名称的原因是该应用程序源自FreeLibrary
不与任何OS API冲突的不同平台。
但是,即使在使用FreeLibrary
32位Windows上也不是问题,因为32位DLL使用名称修改,即该函数存储为_FreeLibrary
,因此不会与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
的符号,而不与kernel32
发生任何冲突?
或者还有其他解决方案可以解决这个问题吗?
我看到的唯一解决方案是将FreeLibrary
重命名为不与我的应用程序的x64版本的OS API冲突的东西,但当然我想避免这种情况,因为它会降低我的应用程序的插件API的一致性。 如果可能的话,我想在所有平台和架构中保留FreeLibrary
名称。
有任何想法吗? 我想如果在32位上有可能在DLL中使用像FreeLibrary
这样的保留名称,那么应该有办法在64位上执行它,不应该在那里吗? 但我不明白……
我不会试图说服编译器破坏函数的名称。 那种方式就是疯狂。
为了澄清,您唯一的问题是链接插件DLL时的重复符号。 应用程序本身不应该关心函数的名称,因为它将通过GetProcAddress
接收的函数指针调用插件入口点。
假设插件不需要调用kernel32.dll中实现的Windows API,您可以尝试从链接器命令中省略kernel32.dll。 (请参阅/NODEFAULTLIB
选项。)如果kernel32.dll不是链接的一部分,则不应该发生冲突。
但这不起作用,因为/MT
命令行中的/MT
意味着您依赖于C运行时库,而C依赖于某些kernel32.dll API。 (另外,您确定要将插件链接到静态运行时库而不是DLL版本吗?)
所以剩下的选择是更改函数的名称。 这应该是微不足道的,因为无论如何你都在移植。 您甚至可以在编译插件时使用预处理器来破解名称,这样您就不需要更改其源代码:
cl /EHsc /c /DFreeLibrary=Plugin_FreeLibrary /Fotest.o test.c
然后更改应用程序中的GetProcAddress
调用以查找Plugin_FreeLibrary
而不是FreeLibrary
,我假设Plugin_FreeLibrary
发生在一个地方。