看看以下示例代码:
__declspec(dllexport) FreeLibrary(void)
{
}
我使用以下小脚本将其构建为DLL:
cl /EHsc /MT /c test.c /Fotest.o
link /dll /out:test.dll test.o
在编译32位体系结构时,这可以正常工作。但是,在编译64位体系结构时,DLL没有构建,我收到以下错误:
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
为什么?为什么它适用于32位但不适用于64位?不应该在32位FreeLibrary
中定义kernel32.dll
符号吗?但是为什么32位链接器没有抱怨然后构建DLL就好了?
这让我很困惑......
答案 0 :(得分:1)
编辑以更正由IInspectable发现的错误并且为了清晰起见
默认调用约定为__cdecl
,这会导致符号名称前缀为下划线:_FreeLibrary
。
>dumpbin /symbols test.o | find "FreeLibrary"
008 00000000 SECT3 notype () External | _FreeLibrary
kernel32.dll中的FreeLibrary
声明为WINAPI
。在32位中,WINAPI
扩展为__stdcall
,因此kernel32的函数名为_FreeLibrary@4
。
>dumpbin /exports kernel32.lib | find "FreeLibrary"
_FreeLibrary@4
_FreeLibraryAndExitThread@8
_FreeLibraryWhenCallbackReturns@8
由于_FreeLibrary
与_FreeLibrary@4
不匹配,因此没有冲突。
默认调用约定是一个four-register fastcall方案,它不会修饰普通C函数的名称。因此test.o定义了一个名为FreeLibrary
的符号:
>dumpbin /symbols test.o | find "FreeLibrary"
008 00000000 SECT3 notype () External | FreeLibrary
此外,WINAPI
宏扩展为空,因此kernel32.dll使用与插件代码相同的默认调用约定。因此它得到了相同的,朴素的符号:
>dumpbin /exports kernel32.lib | find "FreeLibrary"
FreeLibrary
FreeLibraryAndExitThread
FreeLibraryWhenCallbackReturns
这会为您提供两个FreeLibrary
符号,并导致链接器错误。