Ошибка DLL LNK2019 (неразрешенная внешняя ошибка __imp)

Ну, я в основном унаследовал кучу кода, который мне сказали исправить, потому что раньше он работал несколько месяцев назад, но на данный момент это не так. Сама программа, кажется, пронизана ошибками компоновки, и мне удалось исправить некоторые из них. Однако я столкнулся с нерешенным внешним 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-файлы содержат имена функций, которые выдают ошибки. Я также использовал программу обхода зависимостей для просмотра моих DLL-файлов, и она выдала мне некоторые из следующих ошибок:

Ошибка: по крайней мере один модуль имеет неразрешенный импорт из-за отсутствия функции экспорта в неявно зависимом модуле.

Ошибка: были найдены модули с разными типами ЦП.

Основываясь на комментариях других людей, я чувствую, что могу игнорировать 2-ю ошибку. Но я не уверен в первой ошибке. Я также не уверен, что это будет основной причиной проблемы. Это может или не может быть.

Я также заглянул внутрь .lib-файлов, используя VS cmd и средство обхода зависимостей, и кажется, что имена функций, которые не могут быть найдены, перечислены в одном из .lib и .dll.

В плане конфигурации я работаю на платформе режима x64.
Я добавил библиотечные функции DevIL.lib ILU.lib ILUT.lib в командную строку proj -> prop -> linker ->. Я также добавил путь для компоновщика -> общие -> каталог дополнительной библиотеки. Я также попытался возиться с вводом дополнительной зависимости, но это не имеет никакого эффекта. Файлы .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: игнорирование «/ INCREMENTAL» из-за спецификации «/ OPT: ICF»

    // 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 1Invoking 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

Решение

Я добавляю здесь ответ, чтобы немного подытожить приведенные выше комментарии, возможные причины и найти решение для нерешенных ошибок. Я предвосхищу это, говоря, что линкеры, как правило, тупые инструменты низкого уровня. Если символы, на которые есть ссылки в объектных файлах, не совпадают точно с библиотекой, тогда процесс сборки выручает с этими неразрешенными ошибками. Поэтому автору библиотеки dll и клиентам, использующим ее, необходимо приложить некоторые усилия для обеспечения согласованности символов.

Неразрешенные ошибки обычно вызваны одной из следующих причин:

  • Ни проект, ни библиотеки, связанные с ним, не реализуют функцию для этого символа.
  • Библиотеки действительно реализуют функцию, но под другим символом ссылки.
  • Заголовки для библиотеки не были предварительно обработаны или оформлены правильно, что привело к появлению # 2.

Основываясь на том, что описал OP, библиотеки dll, связанные с, выставляют C API. Неясно, какое соглашение о вызовах соблюдает данная библиотека. Экспортированные имена в dll содержат просто неокрашенный названия функций, предполагающие __cdecl условность. Предоставленные соответствующие заголовки, OTOH имеет такую ​​функцию:

ILAPI void ILAPIENTRY ilDeleteImage(const ILuint Num);

который расширяется в это после предварительной обработки:

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

Из этого вы можете заключить три возможных сценария:

  1. Нерешенные функции следуют за __cdecl соглашение и предоставленные заголовки неверны.
  2. Нерешенные функции следуют за __stdcall соглашение и экспортированные имена DLL неверны.
  3. Функции следуют __stdcall но есть неукрашенный выглядеть как __cdecl в длл. Это говорит о том, что .def Возможно, файл был использован для создания DLL.

К сожалению, соглашение о вызове функций, используемое в win32 dll, находится в замешательстве. В стандарте языка C или C ++ нет ничего, что решало бы эту проблему ABI. См мой другой ответ здесь. Поставщик набора инструментов может свободно украшать имена так, как им нравится, но для __cdecl функции это просто неокрашенный или с префиксом ведущих _ нижнее подчеркивание.

WinAPI функции, которые вы найдете, как в kernel32.dll user32.dll gdi32.dll и т.д. также не отделаны, но все же следуют __stdcall, Тем не менее, MSVC сам украшает __stdcall с завершающим амперсандом с общим количеством байтов параметров (например, ilDeleteImage@4) тем самым способствуя путанице. Переопределить как 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 аргумента.

4

Другие решения

У меня была эта ошибка компиляции при сборке проекта с использованием внешних статических библиотек, 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)
0

По вопросам рекламы [email protected]