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