c++ - DLL LNK2019 错误( Unresolved external 错误 __imp)

标签 c++ dll unsatisfiedlinkerror

好吧,我基本上继承了一堆我被告知要修复的代码,因为它在几个月前曾经可以工作,但目前还不行。该程序本身似乎充满了链接错误,我能够修复其中的一些错误。但是,我遇到了 LNK2019 Unresolved external _imp 错误,其中主要使用的某些功能未解决。由于“_imp”,我假设这是与从 .dll 或 .lib 文件导入有关的问题。

首先,我有三个 .lib 文件,我相信它们可以正确地导入到 VS2010 中,并且我已将平台配置为 64x。还有与 .lib 文件对应的 .dll 文件。包含这些错误函数声明的 .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 之一中。

在配置方面,我在 Release模式 x64 平台上运行。
我在 proj -> prop -> 链接器 -> 命令行中添加了“DevIL.lib ILU.lib ILUT.lib”库函数。我还添加了链接器的路径 -> 常规 -> 附加库目录。我也尝试过弄乱输入附加依赖项,但它没有效果。 .lib 和 .dll 文件也放在同一目录中。在 proj 属性配置中,我没有在任何地方提到 .dll(我应该这样做吗?我已经在不同的位置尝试过,但只会产生更多错误)我知道有很多关于链接 2019 错误的帖子,但我没有很好到目前为止,我在寻找我的特定问题时很幸运。我将不胜感激任何建议、评论或链接,我可以在其中找到关于为什么会发生这种情况的线索

这是来自日志的链接器命令:

这是来自构建日志本身的链接器命令:

Link: 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 x64\Release\dff.exe.embed.manifest.res x64\Release\acquisition.obj x64\Release\azmemutil.obj x64\Release\dff.obj x64\Release\fft.obj x64\Release\FocusMeasure.obj x64\Release\ge.obj x64\Release\stdafx.obj DevIL.lib ILU.lib ILUT.lib 1>LINK : warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:ICF' specification


    // 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 但没有效果。

最佳答案

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

根本原因

Unresolved 错误通常由以下原因之一引起:

  • 项目和链接的库都没有实现该符号的功能。
  • 这些库实际上确实实现了该功能,但使用了不同的引用符号。
  • 库的 header 未正确预处理或修饰,从而导致#2。

  • 狩猎

    基于 OP 所描述的链接的 dll 库公开了一个 C API。目前尚不清楚相关库遵循什么调用约定。 dll 中的导出名称包含简单的未修饰函数名称,建议使用 __cdecl。惯例。提供的相应标题,OTOH 具有如下功能:
    ILAPI void ILAPIENTRY ilDeleteImage(const ILuint Num);
    

    预处理后扩展为:
    __declspec(dllimport) void __stdcall ilDeleteImage(const ILuint Num);
    

    由此您可以得出三种可能的情况:
  • Unresolved 函数遵循 __cdecl约定和提供的标题是错误的。
  • Unresolved 函数遵循 __stdcall约定和导出的 dll 名称是错误的。
  • 函数如下__stdcall但未装饰看起来像 __cdecl在dll中。这表明 .def文件可能已用于构建有问题的 dll。

  • 悲伤的事态

    不幸的是,win32 dll 中遵循的函数调用约定处于困惑状态。语言标准 C 或 C++ 中没有任何内容可以解决此 ABI 问题。见我的其他 answer here .工具链供应商可以随意装饰名称,但通常为 __cdecl功能它是普通的未装饰或带有前缀的前导 _下划线。

    您可以找到的 WinAPI 函数,例如 kernel32.dll user32.dll gdi32.dll等也未装饰,但仍遵循 __stdcall .但是,MSVC 本身装饰了 __stdcall带有参数总字节数的尾随&符号(例如 ilDeleteImage@4 )从而导致混淆。覆盖如何 LINK装饰功能,您必须提供.def指定新名称别名的文件。 See here更多细节。

    寻找真正的约定

    假设您无权访问用于构建 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 个参数。

    关于c++ - DLL LNK2019 错误( Unresolved external 错误 __imp),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17397423/

    相关文章:

    c++ - 用我自己的实现替换 getpid

    c++ - 在编译时构建开关

    c++ - SFML - 粒子系统 vector 超出范围

    windows - 如何创建 DLL 初始化例程?

    c# - 转储存储为 dll 文件的 SQLite 数据库?

    c++ - LoadLibrary调用DLL时查找依赖的DLL

    C++ linux 应用程序在长时间运行后停止系统。如何寻找原因?

    android - UnsatisfiedLinkError In Android 4.4 libDevil cannot locate symbol "png_set_longjmp_fn"

    android - JNI_OnLoad 返回错误版本 (-1)

    javafx - javafx 的 UnsatisfiedLinkError