首页 文章

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

提问于
浏览
2

好吧,我基本上继承了一堆我被告知修复的代码,因为它曾经在几个月前工作,但目前还没有 . 该程序本身似乎充满了链接错误,我能够解决其中的一些问题 . 但是我遇到了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 - > prop - > linker - >命令行中添加了“DevIL.lib ILU.lib ILUT.lib”库函数 . 我还添加了链接器的路径 - > general - >其他库目录 . 我也试过搞乱输入附加依赖但它没有效果 . .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 \ 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:警告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.

Build 失败 .

以防万一我也尝试写#define _IL_BUILD_LIBRARY但没有效果 .

2 回答

  • 4

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

    根本原因

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

    • 项目和链接的库都没有实现该符号的功能 .

    • 库实际上实现了函数,但是在不同的引用符号下 .

    • 库的 Headers 未经过预处理或正确装饰,从而导致#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问题 . 见我的其他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个参数 .

  • 0

    使用外部静态库,QDBM和PCRE构建项目时出现此编译错误:

    _main.obj : error LNK2001: unresolved external symbol __imp__dpversion
    _main.obj : error LNK2001: unresolved external symbol __imp__regcomp
    

    我已经正确配置了这些外部项目来构建静态库, but 我忘了在我自己的代码中定义正确的预处理器定义,这些代码使用这些库来启用静态链接 .

    因此,当他们从QDBM和PCRE导入标头时,他们添加了一个不应该存在的 __declspec(dllimport) .

    我将缺少的预处理器定义添加到我的构建系统,修复了错误:

    -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)
    

相关问题