链接器读取库,但在其中找不到符号?未解析的外部符号,但仅适用于 Win32 而不是 x64
Linker reads library but can't find symbol within it? Unresolved External Symbol but only for Win32 and not x64
Background
我有一个 C 天文库,我想在我的 C++ 应用程序中使用它。
我已经在Visual Studio 2012 Express中以Win32和x64配置构建了它,并且:
- 动态调试 (.dll)
- 动态释放 (.dll)
- 静态调试 (.lib)
- 静态发布 (.lib)
。所以这是 2 * 4 = 8 个二进制文件(不包括 *.pdb 个文件等)
然后我使用批量构建来构建所有配置,因为有时我需要不同的版本,我发现在开始时完成所有工作并通过一个过程比在容易混淆时随意完成要好。
在我的C++应用程序中,我有相同的过程,并根据名称链接到库。具体来说,在我的项目属性链接器->输入字段中,我有:
SwissEphemeris_$(Platform)_$(Configuration).lib
。并且已正确设置其他库目录。一切似乎都是对的。库文件位于库目录中。
这是麻烦:
在我总共拥有的 8 个配置中,除了两个之外,所有配置都正确链接和构建:
- Win32 动态调试
- Win32 动态发布
对于这两种配置,相同的链接器错误:
main.obj : error LNK2019: unresolved external symbol _swe_close referenced in function _main
我已经尝试了一些诊断或修复的方法,但没有一个奏效:
- 在新的解决方案/项目中从头开始重建库,确保 Win32 和 x64 之间没有偏差,除了
/MACHINE
链接器标志之外 - 创建一个新的解决方案/项目,只有一个main(),该 main() 在 Win32 动态调试配置中
swe_close()
调用此库函数并链接到该 *.lib。
错误始终相同,如上所示。我已经打开了详细的链接器输出,真正让我困惑的是链接器似乎成功地找到并读取了SwissEphemeris_Win32_DynamicDebug.lib
文件,但仍然无法在其中找到swe_close()
符号。即使dumpbin.exe
表明,在我需要的所有其他符号中,该符号都在其中。
1> Unused libraries:
1> E:DataCodelibSwissEphemerisSwissEphemeris_Win32_DynamicDebug.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86user32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86gdi32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86winspool.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86comdlg32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86advapi32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86shell32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86ole32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86oleaut32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86uuid.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86odbc32.lib
1> C:Program Files (x86)Windows Kits8.0libwin8umx86odbccp32.lib
1> E:ProgramsVS2012VClibOLDNAMES.lib
1>
1>main.obj : error LNK2019: unresolved external symbol _swe_close referenced in function _main
1>E:DataCodetestDebugtest.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
挠头
有没有人知道为什么链接器找不到该符号,并且仅适用于 Win32 动态调试/发布,但适用于所有其他 6 种配置?
为了确保库确实是为 Win32/X86 构建的,下面是库项目属性中的链接器命令行选项:
(路径与上面的路径略有不同 - 链接器尝试查找库 - 因为库首先构建到这个"bin"目录,然后复制到库目录,这肯定会发生。
/OUT:"E:DataCodelibBuildersSwissEphemerisbinSwissEphemeris_Win32_DynamicDebug.dll"
/MANIFEST
/NXCOMPAT
/PDB:"E:DataCodelibBuildersSwissEphemerisbinSwissEphemeris_Win32_DynamicDebug.pdb"
/DYNAMICBASE
/IMPLIB:"E:DataCodelibBuildersSwissEphemerisbinSwissEphemeris_Win32_DynamicDebug.lib"
/DEBUG
/DLL
/MACHINE:X86
/SAFESEH
/PGD:"E:DataCodelibBuildersSwissEphemerisbinSwissEphemeris_Win32_DynamicDebug.pgd"
/SUBSYSTEM:CONSOLE
/MANIFESTUAC:"level='asInvoker' uiAccess='false'"
/ManifestFile:"E:DataCodelibBuildersSwissEphemerisobjSwissEphemeris_Win32_DynamicDebugSwissEphemeris_Win32_DynamicDebug.dll.intermediate.manifest"
/ERRORREPORT:PROMPT
/NOLOGO
dumpbin.exe /exports
输出
E:DataCodelibSwissEphemeris>dumpbin /exports SwissEphemeris_Win32_DynamicDebug.dll
Microsoft (R) COFF/PE Dumper Version 11.00.50727.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file SwissEphemeris_Win32_DynamicDebug.dll
File Type: DLL
Section contains the following exports for SwissEphemeris_Win32_DynamicDebug.dll
00000000 characteristics
528041A6 time date stamp Sun Nov 10 19:32:06 2013
0.00 version
1 ordinal base
131 number of functions
131 number of names
ordinal hint RVA name
1 0 00001195 _swe_azalt@40 = @ILT+400(_swe_azalt@40)
2 1 000011FE _swe_azalt_d@28 = @ILT+505(_swe_azalt_d@28)
3 2 000012AD _swe_azalt_rev@24 = @ILT+680(_swe_azalt_rev@24)
4 3 00001357 _swe_azalt_rev_d@20 = @ILT+850(_swe_azalt_rev_d@20)
5 4 0000126C _swe_calc@24 = @ILT+615(_swe_calc@24)
6 5 000011BD _swe_calc_d@20 = @ILT+440(_swe_calc_d@20)
7 6 0000105F _swe_calc_ut@24 = @ILT+90(_swe_calc_ut@24)
8 7 00001235 _swe_calc_ut_d@20 = @ILT+560(_swe_calc_ut_d@20)
9 8 00001389 _swe_close@0 = @ILT+900(_swe_close@0)
10 9 00001212 _swe_close_d@4 = @ILT+525(_swe_close_d@4)
...
在库头文件中定义用于导出的 DLL 的位置。仅定义了MAKE_DLL
和PASCAL
,因此此处唯一处于活动状态的语句是 #define PASCAL_CONV PASCAL
和 #else /* 32bit DLL */
块。
/* DLL defines */
#ifdef MAKE_DLL
#if defined (PASCAL)
#define PASCAL_CONV PASCAL
#else
#define PASCAL_CONV
#endif
#ifdef MAKE_DLL16 /* 16bit DLL */
/* We compiled the 16bit DLL for Windows 3.x using Borland C/C++ Ver:3.x
and the -WD or -WDE compiler switch. */
#define EXP16 __export
#define EXP32
#else /* 32bit DLL */
/* To export symbols in the new DLL model of Win32, Microsoft
recommends the following approach */
#define EXP16
#define EXP32 __declspec( dllexport )
#endif
#else
#define PASCAL_CONV
#define EXP16
#define EXP32
#endif
。然后声明swe_close()
的实际函数如下所示:
ext_def( void ) swe_close(void);
他们使用大量的宏观步法,因此这解析为:
extern __declspec(dllexport) void far PASCAL swe_close();
我不熟悉far
和PASCAL
.这些会干扰什么吗?为什么 x64 配置可以正常工作,但 Win32 会中断?
9 8 00001389 _swe_close@0 = @ILT+900(_swe_close@0)
DLL 中的函数名称与链接器要查找的函数名称之间存在明显的不匹配。 DLL 项目已将其编译为__stdcall函数,您可以从 @0 修饰中看出链接器正在寻找__cdecl函数。
这可能是由编译器选项/Gd vs/Gz 引起的,但这不太可能,您已经检查过它。 更可能的原因是声明导出函数的 .h 文件,以便另一个项目可以 #include 它并使用 DLL。 这通常是用宏汤完成的,以便__declspec(dllexport)和__declspec(dllimport)属性是正确的用法。 调用约定应始终显式声明,通常使用另一个宏。 就像 WINAPI 宏在 Windows SDK 标头中的使用方式一样。 我会在汤上花钱
- FLTK 2.0构建和演示,适用于VS2019的2011年左右的代码库
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- "string.h"在构建适用于iOS的qt应用程序中找不到消息
- 适用于 WebView2 旧版本的示例应用程序
- 在 NVIDIA GEFORCE GTX 1050 上下载适用于 Windows 10 的 openCL 1.2
- __attribute__(优化(0))) 是否适用于"recursively"?
- 为什么 std::erase(std::erase_if) 不是适用于<algorithm>任何容器的模板?
- 使用一个参数的模板函数时出错(适用于 2)
- 使用 适用于 Android 和 iOS 的 tf-lite C++ API
- 为什么这适用于 G++ 而不是 CLANG?
- 适用于 macOS 的 Xcode 应用程序。这就是我设置从USB麦克风输入获取音频的方式。一年前工作,现在没有了。为什么
- 适用于 Linux 的 c++ 上的代理脚本
- 为什么我的 SFINAE 表达式不再适用于 GCC 8.2?
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 有没有适用于Windows.lib文件的GNU二进制文件描述符(BFD)
- 模板函数仅适用于VS
- 如何在cmake中包含适用于g++或viceversa的库
- 适用于win32、linux、mac的POSIX C包装器
- 链接器读取库,但在其中找不到符号?未解析的外部符号,但仅适用于 Win32 而不是 x64
- 重复符号仅适用于iOS模拟器版本