DLL LNK2019错误(未解析的外部错误__imp)
DLL LNK2019 error (unresolved external error __imp)
我基本上继承了一堆代码,因为几个月前它还可以工作,但现在不行了。程序本身似乎充满了链接错误,我能够修复其中的一些错误。然而,我遇到了一个LNK2019未解析的外部_imp错误,其中主函数中使用的某些函数未解析。由于"_imp",我认为这是一个与从.dll或.lib文件导入有关的问题。
首先,我有三个.lib文件,我相信它们正确地导入到VS2010中,并且我已经将平台配置为64x。还有与.lib文件相对应的.dll文件。包含这些充满错误的函数声明的.h文件包含类似的内容
ILAPI void ILAPIENTRY ilDeleteImage(const ILuint Num);
不幸的是,我猜这个定义是在.dll文件中定义的,我自己没有写,所以我不确定。但由于这是以前工作过的代码,我相信我会收到这个错误,因为链接器找不到定义,而不是def/dell不匹配的原因。
当我将鼠标悬停在ILAPI上时,它会显示:"ILAPI __declspec(dllimport)"我目前的猜测是,程序导入.lib文件,而.lib文件使用.dll文件来获得函数的定义。我相信我正在导入.lib文件,因为编译器不再不断告诉我找不到特定的.lib文件。然而,我担心它可能没有连接.dll文件。我有些不确定。我已经打开了.lib文件,并且.lib文件包含出现错误的函数的名称。我还使用了依赖性助行程序来查看我的DLL文件,它给了我以下一些错误:
错误:由于隐式依赖模块中缺少导出函数,至少有一个模块具有未解析的导入。
错误:找到了具有不同CPU类型的模块。
根据其他人的评论,我觉得我可以忽略第二个错误。但我不确定第一个错误。我也不确定这是否是问题的根本原因。可能是也可能不是。
我还使用VS cmd和依赖项walker查看了.lib文件的内部,似乎找不到的函数的名称列在.lib和.dll.中
在配置方面,我正在x64平台上运行发布模式。我在proj->prop->linker->commandline中添加了"DevIL.lib ILU.lib ILUT.lib"库函数。我还添加了链接器->常规->附加库目录的路径。我也尝试过扰乱输入附加依赖关系,但没有效果。.lib和.dll文件也放在同一目录中。在proj属性配置中,我在任何地方都没有提到.dll(我应该提到吗?我在不同的位置尝试过,但只是造成了更多的错误)我知道有很多关于链接2019错误的帖子,但到目前为止,我在搜索我的特定问题时运气不好。我将感谢任何建议,评论,或链接,在那里我可以找到线索,为什么会发生
这是日志中的链接器命令:
这是来自构建日志本身的链接器命令:
链接:C: \Program Files(x86)\Microsoft Visual Studio 10.0\VC\bin\x86_amd64\link.exe/ERRORREPORT:PROMPT/OUT:"x64\Release \dff.exe"/VERBOSE/INCREMENTAL/NOLOGO/LIBPATH:C:\Users\Sub2\Desktop\ddff\x64\Release/MANIFEST/ManifestFile:"x64\Release\dff.exe.intermediate.manifest"/MANIFESTUAC:"level='asInvoker'uiAccess='false'"/DEBUG/PDB:"C:\Users\Sub2\Desktop\dff\x64\Release \dff.PDB"/子系统:控制台/OPT:REF/OPT:ICF/TLBID:1/DYNAMICBASE/NXCOMPAT/IMPLIB:"x64\Release\dff.lib"/MACHINE:x64x64\Release \dff.exe.embed.manifest.resx64 \发布\获取.objx64\Release \azmemutil.objx64\Release \dff.objx64\Release \fft.objx64\Release \FocusMeasure.objx64\Release \ge.objx64\Release \ stdafx.obj DevIL.lib ILU.lib ILUT.lib1> 链接:警告LNK4075:由于"/OPT:ICF"规范而忽略"/INCREMENTAL"
// This is from Win32's <wingdi.h> and <winnt.h>
#if defined(__LCC__)
#define ILAPI __stdcall
#elif defined(_WIN32) //changed 20031221 to fix bug 840421
#ifdef IL_STATIC_LIB
#define ILAPI
#else
#ifdef _IL_BUILD_LIBRARY
#define ILAPI __declspec(dllexport)
#else
#define ILAPI __declspec(dllimport)
#endif
#endif
#elif __APPLE__
#define ILAPI extern
#else
#define ILAPI
#endif
还有:
#define ILAPIENTRY __stdcall
接近错误时生成日志信息:
Found KERNEL32_NULL_THUNK_DATA
Referenced in kernel32.lib(KERNEL32.dll)
Loaded kernel32.lib(KERNEL32.dll)
Searching C:UsersSub2Desktopdffx64ReleaseDevIL.lib:
Searching C:UsersSub2Desktopdffx64ReleaseILU.lib:
Searching C:UsersSub2Desktopdffx64ReleaseILUT.lib:
Searching C:Program Files (x86)Microsoft Visual Studio 10.0VClibamd64MSVCRT.lib:
Searching C:Program Files (x86)Microsoft Visual Studio 10.0VClibamd64OLDNAMES.lib:
Searching C:Program Files (x86)Microsoft Visual Studio 10.0VClibamd64msvcprt.lib:
Finished searching libraries
Finished pass 1
Invoking CVTRES.EXE:
/machine:amd64
/verbose
/out:"C:UsersSub2AppDataLocalTemplnk92ED.tmp"
/readonly
"x64Releasedff.exe.embed.manifest.res"
Microsoft (R) Windows Resource To Object Converter Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
adding resource. type:MANIFEST, name:1, language:0x0409, flags:0x30, size:2
1>dff.obj : error LNK2019: unresolved external symbol __imp_iluGetImageInfo referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_iluImageParameter referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilDeleteImages referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilSaveImage referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_iluFlipImage referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_iluScale referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilTexImage referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilCopyPixels referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilGetError referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilLoadImage referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilBindImage referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilGenImages referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilInit referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilGetInteger referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilEnable referenced in function main
1>dff.obj : error LNK2019: unresolved external symbol __imp_ilOriginFunc referenced in function main
1>x64Releasedff.exe : fatal error LNK1120: 16 unresolved externals
1>Done Building Project "C:UsersSub2Desktopdffdff.vcxproj" (rebuild target(s)) -- FAILED.
生成失败。
以防万一,我也试过写#define _IL_BUILD_BRARY,但没有效果。
我在这里添加了一个答案,总结了上面的评论、可能的根本原因,并找到了解决未解决错误的方法。在这之前,我会说链接器往往是愚蠢的低级工具。如果对象文件中引用的符号与库不完全匹配,那么构建过程就会出现那些未解决的错误。因此,dll库的作者和使用它的客户端需要付出一些努力来确保符号一致。
根本原因
未解决的错误通常由以下原因之一引起:
- 项目和链接的库都没有实现该符号的函数
- 这些库实际上实现了该函数,但使用了不同的参考符号
- 库的头没有经过正确的预处理或修饰,从而导致#2
狩猎
根据OP的描述,链接的dll库公开了一个C API。目前尚不清楚该图书馆遵循的是什么呼叫惯例。dll中导出的名称包含未修饰的函数名,这表明存在__cdecl
约定。提供的相应标题,OTOH具有如下功能:
ILAPI void ILAPIENTRY ilDeleteImage(const ILuint Num);
经过预处理后扩展为
__declspec(dllimport) void __stdcall ilDeleteImage(const ILuint Num);
由此可以得出三种可能的情况:
- 未解析的函数遵循
__cdecl
约定,并且提供的标头是错误的 - 未解析的函数遵循
__stdcall
约定,并且导出的dll名称错误 - 函数遵循
__stdcall
,但未修饰,看起来像dll中的__cdecl
。这表明.def
文件可能已用于构建有问题的dll
悲伤的现状
不幸的是,win32 dll中遵循的函数调用约定处于令人困惑的状态。语言标准C或C++中没有任何内容可以解决ABI问题。请在此处查看我的另一个答案。工具链供应商可以随心所欲地装饰名称,但通常对于__cdecl
函数,它是完全未装饰的或带有前缀的前导_
下划线。
您发现的WinAPI函数,如kernel32.dll
user32.dll
gdi32.dll
等,也未经过修饰,但遵循__stdcall
。然而,MSVC本身用尾随的"与"和参数的总字节数(例如ilDeleteImage@4
)来修饰__stdcall
,从而导致混乱。要覆盖LINK
修饰函数的方式,必须提供一个指定新名称别名的.def
文件。请参阅此处了解更多详细信息。
寻找真正的约定
假设您没有访问用于构建dll的源代码的权限,我可以想出两种方法来确定所使用的真正约定。
创建一个调用dll函数的最小测试应用程序,就像它使用__cdecl
一样,并查看它是否崩溃和烧录。这是一种更简单、更直接的方法,你不必理解组装即可完成
第二种方法是,执行相同的操作,但在测试应用程序中插入程序集断点,并通过调试器执行单步指令来运行它。请确保选择一个dll函数,该函数至少使用一个参数。例如:
// pullin dll headers
// etc..
int main()
{
__asm int 3;
ilDeleteImage(0xdecafbad);
}
这将在dll函数调用之前中断并将控制权交还给调试器。从这里开始,在程序集级别执行单个步骤,直到您到达ilDeleteImage
的函数序言。
; function prologue
push ebp
mov ebp, esp
; function implemention
; more opcodes here
; ...
; function epilogue
mov esp, ebp
pop ebp
ret 0x8
检查函数返回中使用了何种形式的ret
。ret
助记符后面的数字参数指示esp
堆栈指针的增量。任何大于0的数字都表示__stdcall
函数。上面的形形反汇编显示了一个__stdcall
函数,它释放了堆栈上的8个字节,这也暗示了这个函数需要2个参数。
我在使用外部静态库、QDBM和PCRE构建项目时出现了此编译错误:
_main.obj : error LNK2001: unresolved external symbol __imp__dpversion
_main.obj : error LNK2001: unresolved external symbol __imp__regcomp
我已经正确地配置了这些外部项目来构建静态库,但我忘记在自己的代码中定义正确的预处理器定义,该代码使用这些库来启用静态链接。
因此,当他们从QDBM和PCRE导入标头时,他们添加了一个不应该存在的__declspec(dllimport)
(用于静态链接),因此他们试图从不存在的DLL导入符号。
我在构建系统中添加了缺失的预处理器定义,修复了错误:
-DQDBM_STATIC -DPCRE_STATIC
这意味着在我的CMakeLists.txt
文件中添加以下行:
# Tell QDBM not to build itself as a DLL, because we want to link statically to it.
target_compile_definitions(qdbm PUBLIC -DQDBM_STATIC)
target_compile_definitions(lib_common PUBLIC -DPCRE_STATIC)
- 使用外部SDK工具链文件在VisualStudio上生成项目编译错误
- spdlog标头仅与外部fmt一起使用.spdlog错误:'内部':不是'fmt'
- 我收到错误LNK2001:未解析的外部符号(C++代码)
- Visual Studio 2017 中的 QtMetaObject 未解决的外部错误
- 外部"C"拆卸导致奇怪的链接器错误
- C++指针无法在函数外部传递值和分段错误(核心转储)错误
- 在Embarcadero C++ Builder中生成的DLL未解决的外部链接错误
- 可视抽象类 c++(错误 LNK 2001:未解析的外部符号)
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- 当 lib 已添加到其他依赖项时,如何在 VS 中调试未解析的外部符号错误
- 错误LNK2019未解析的外部符号"public: __thiscall SLinkList<char>::SLinkList<char>(void)"
- 外部函数在 main() 上调用时返回分段错误 11.(C++)
- 引入参数化构造函数后显示 LNK 2019 未解析外部符号的代码错误
- 每次我要使用外部资源时,我都会得到:collect2。exe:错误 ld 返回 1 退出状态
- 链接器错误:切换到unicode生成给出:未解析的外部符号WinMain
- C#WPF和C++/CLI以及C++在C++/CLI中添加外部库错误
- 函数 LNK2019 "int __cdecl __scrt_common_main_seh(void)" 中引用的未解析外部符号主错误 (?__scrt_common_main_seh@@YAHXZ
- C++:在"try"外部创建的类型会导致错误,但在内部不会
- 编译错误外部接口Simulink
- 为什么这会给出多个定义错误:外部 int i;国际 i;.