DLL LNK2019错误(未解决的外部错误__imp)

时间:2013-07-01 04:24:35

标签: c++ dll unsatisfiedlinkerror

嗯,我基本上继承了一堆我被告知修复的代码,因为它曾经在几个月前工作,但目前还没有。该程序本身似乎充满了链接错误,我能够解决其中的一些问题。但是,我遇到了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但没有效果。

2 个答案:

答案 0 :(得分:4)

我在这里添加一个答案,总结一下上述评论,可能的根本原因并找到未解决的错误的解决方案。我将在前言中说接头往往是愚蠢的低级工具。如果目标文件中引用的符号与库完全不匹配,则构建过程将解除那些未解决的错误。因此,dll库的作者和使用它的客户需要付出一些努力来确保符号一致。

根本原因

未解决的错误通常是由以下原因之一引起的:

  • 项目和链接的库都没有实现该符号的功能。
  • 这些库实际上实现了这个功能,但是在不同的参考符号下。
  • 库的标题未经过预处理或正确装饰,从而导致#2。

亨特

基于OP描述的链接的dll库暴露C API。目前还不清楚有问题的图书馆正在遵循什么样的呼叫惯例。 dll中的导出名称包含 plain undecorated 函数名称,表示__cdecl约定。提供相应的标题,OTOH具有如下函数:

ILAPI void ILAPIENTRY ilDeleteImage(const ILuint Num);

在预处理后扩展到此:

__declspec(dllimport) void __stdcall ilDeleteImage(const ILuint Num);

由此可以得出三种可能的情况:

  1. 未解析的函数遵循__cdecl约定,提供的标题错误。
  2. 未解析的函数遵循__stdcall约定,导出的dll名称错误。
  3. 这些函数遵循__stdcall,但未修饰在dll中看起来像__cdecl。这表明可能已使用.def文件来构建有问题的dll。
  4. 悲伤的事情

    不幸的是,在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)
相关问题