嗯,我基本上继承了一堆我被告知修复的代码,因为它曾经在几个月前工作,但目前还没有。该程序本身似乎充满了链接错误,我能够解决其中的一些问题。但是,我遇到了LNK2019未解决的外部_ imp错误,其中主要使用的某些功能未得到解决。由于“ _imp”我假设它是一个与从.dll或.lib文件导入相关的问题。
首先,我有三个.lib文件,我相信我们正确地将它们导入到VS2010中,并且我已将平台配置为64x。还有.dll文件与.lib文件对应。包含这些错误驱动函数声明的.h文件包含类似
的内容ILAPI void ILAPIENTRY ilDeleteImage(const ILuint Num);
不幸的是我猜测定义是在.dll文件中定义的,我没有写自己,所以我不确定。但是因为这是在我相信我收到此错误之前有效的代码,因为链接器找不到定义而不是def / decl不匹配原因。
当我将鼠标悬停在ILAPI上时,它指出:“ILAPI __declspec(dllimport)” 我目前的猜测是程序导入.lib文件,而.lib文件使用.dll文件来获取函数的定义。我相信我正在导入.lib文件,因为编译器不再继续告诉我它找不到特定的.lib文件。但是我担心它可能没有连接.dll文件。我有点不确定。我打开了.lib文件,.lib文件包含给出错误的函数的名称。我还使用了依赖walker程序来查看我的DLL文件,它一直给我一些以下错误:
错误:由于隐式相关模块中缺少导出功能,至少有一个模块具有未解析的导入。
错误:找到了具有不同CPU类型的模块。
根据其他人的评论,我觉得我可以忽略第二个错误。但我不确定第一个错误。我也不确定这是否是问题的根本原因。它可能是也可能不是。
我还使用VS cmd和依赖walker查看了.lib文件,看起来无法找到的函数名称列在.lib和.dll之一中。
在配置方面,我在发布模式x64平台上运行。 我在proj中添加了“DevIL.lib ILU.lib ILUT.lib”库函数 - >道具 - >链接器 - >命令行。我还添加了链接器的路径 - >一般 - >附加库目录。我也试过搞乱输入附加依赖但它没有效果。 .lib和.dll文件也放在同一目录中。在proj属性配置中我没有提到任何地方的.dll(我应该?我已经在不同的地方尝试但只是创造了更多的错误)我明白有关于链接2019错误的大量帖子但我没有好到目前为止,我在搜索我的特定问题时运气好我会感谢任何建议,评论或链接,我可能会找到一个线索,为什么会发生这种情况
这是来自log:
的链接器命令这是构建日志本身的链接器命令:
链接: 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 \ dff \ 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” / SUBSYSTEM:CONSOLE / OPT:REF / OPT:ICF / TLBID:1 / DYNAMICBASE / NXCOMPAT /IMPLIB:"x64\Release\dff.lib“/ MACHINE:X64 64 \发布\ dff.exe.embed.manifest.res 64 \发布\ acquisition.obj 64 \发布\ azmemutil.obj 64 \发布\ dff.obj 64 \发布\ fft.obj 64 \发布\ FocusMeasure.obj 64 \发布\ ge.obj x64 \ Release \ stdafx.obj DevIL.lib ILU.lib ILUT.lib 1> LINK:警告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:\Users\Sub2\Desktop\dff\x64\Release\DevIL.lib:
Searching C:\Users\Sub2\Desktop\dff\x64\Release\ILU.lib:
Searching C:\Users\Sub2\Desktop\dff\x64\Release\ILUT.lib:
Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64\MSVCRT.lib:
Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64\OLDNAMES.lib:
Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64\msvcprt.lib:
Finished searching libraries
Finished pass 1
Invoking CVTRES.EXE:
/machine:amd64
/verbose
/out:"C:\Users\Sub2\AppData\Local\Temp\lnk92ED.tmp"
/readonly
"x64\Release\dff.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>x64\Release\dff.exe : fatal error LNK1120: 16 unresolved externals
1>Done Building Project "C:\Users\Sub2\Desktop\dff\dff.vcxproj" (rebuild target(s)) -- FAILED.
构建失败。
以防万一我也尝试写#define _IL_BUILD_LIBRARY但没有效果。
答案 0 :(得分:4)
我在这里添加一个答案,总结一下上述评论,可能的根本原因并找到未解决的错误的解决方案。我将在前言中说接头往往是愚蠢的低级工具。如果目标文件中引用的符号与库完全不匹配,则构建过程将解除那些未解决的错误。因此,dll库的作者和使用它的客户需要付出一些努力来确保符号一致。
未解决的错误通常是由以下原因之一引起的:
基于OP描述的链接的dll库暴露C API。目前还不清楚有问题的图书馆正在遵循什么样的呼叫惯例。 dll中的导出名称包含 plain undecorated 函数名称,表示__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问题。查看我的其他answer here。工具链供应商可以自由地装饰他们喜欢的名称,但是__cdecl
类似于_
函数,它是简单的未修饰或带有前缀的kernel32.dll
下划线。
您找到的WinAPI功能,如user32.dll
gdi32.dll
__stdcall
等,也未修饰,但仍然遵循__stdcall
。但是,MSVC本身使用尾随符号装饰ilDeleteImage@4
,其中包含参数的总字节数(例如LINK
),从而导致混淆。要覆盖.def
装饰函数的方式,您必须提供一个指定新名称别名的__cdecl
文件。 See here了解更多详情。
假设您无权访问用于构建dll的源代码,我可以考虑使用两种方法来识别所使用的实际约定。
创建一个调用dll函数的最小测试应用程序,就好像它使用// pullin dll headers
// etc..
int main()
{
__asm int 3;
ilDeleteImage(0xdecafbad);
}
一样,看它是否崩溃和烧伤。这是更简单直接的方法,您无需了解汇编就可以了。
第二种方法,您可以执行相同操作,但将汇编断点插入到测试应用程序中,并通过调试器执行单步指令。确保选择至少一个参数的dll函数。例如:
ilDeleteImage
这会在dll函数调用之前断开并将控制权交还给调试器。从汇编级别开始,直到达到 ; function prologue
push ebp
mov ebp, esp
; function implemention
; more opcodes here
; ...
; function epilogue
mov esp, ebp
pop ebp
ret 0x8
的功能序言。
ret
检查函数返回时使用的ret
形式。 esp
助记符后面的数字参数表示递增__stdcall
堆栈指针的数量。任何数字> 0表示__stdcall
函数。上面的假设反汇编显示了一个{{1}}函数在堆栈上释放了8个字节,这也暗示了这个函数有2个参数。
答案 1 :(得分:0)
使用外部静态库,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中导入符号。 / p>
我在构建系统中添加了缺少的预处理器定义,修复了错误:
-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)