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

Ну, я в основном унаследовал кучу кода, который мне сказали исправить, потому что он работал несколько месяцев назад, но сейчас не работает. Сама программа, кажется, изобилует ошибками компоновки, и я смог исправить некоторые из них. Однако я столкнулся с неразрешенной внешней ошибкой _imp LNK2019, когда некоторая функция, используемая в основном, не разрешена. из-за "_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 -> commandline. Я также добавил путь для компоновщика -> общий -> каталог дополнительной библиотеки. Я также пытался возиться с дополнительной зависимостью ввода, но это не дало никакого эффекта. Файлы .lib и .dll также помещаются в тот же каталог. В конфигурации свойства proj я нигде не упоминаю .dll (я должен? Я пробовал в разных местах, но просто создает больше ошибок) Я понимаю, что есть масса сообщений об ошибке link 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>ССЫЛКА: предупреждение 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 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, но безрезультатно.


person user2427671    schedule 01.07.2013    source источник
comment
Можете ли вы добавить полную команду компоновщика, которая используется для выполнения ссылки? Вы должны найти это где-то в журнале сборки.   -  person greatwolf    schedule 02.07.2013
comment
О, не могли бы вы также добавить, как выглядит предварительно обработанная форма ilDeleteImage для источника, который делает вызов?   -  person greatwolf    schedule 02.07.2013
comment
вот командная строка компоновщика, которую я вытащил из свойства: /OUT:x64\Release\dff.exe /VERBOSE /INCREMENTAL /NOLOGO /LIBPATH:C:\Users\Sub2\Desktop\dff\x64\Release /MANIFEST /ManifestFile: x64\Release\dff.exe.intermediate.manifest/ALLOWISOLATION/MANIFESTUAC:level='asInvoker' uiAccess='false' /DEBUG/PDB:C:\Users\Sub2\Desktop\dff\x64\Release\dff.pdb / ПОДСИСТЕМА: КОНСОЛЬ /OPT:REF /OPT:ICF /PGD:C:\Users\Sub2\Desktop\dff\x64\Release\dff.pgd /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X64 /ERRORREPORT:QUEUE   -  person user2427671    schedule 02.07.2013
comment
ну, я считаю, что ilDeleteImage определен в DLL/.lib, поэтому я не вижу фактического его определения, если вы об этом спрашиваете. Сорри, я немного новичок в этой dll.   -  person user2427671    schedule 02.07.2013
comment
вот команда компоновщика из самого журнала сборки: размещено по проблеме   -  person user2427671    schedule 02.07.2013
comment
я предоставил больше информации через редактирование, когда ILAPI определяется как declspec (dllimport)   -  person user2427671    schedule 02.07.2013
comment
Основываясь на новой информации, можете ли вы проверить, что компилятор на самом деле видит __declspec(dllimport) void __stdcall ilDeleteImage(const ILuint Num); после предварительной обработки? Это важно, потому что это напрямую влияет на то, как будет оформлена функция и, в конечном счете, на то, какой символ ищет компоновщик.   -  person greatwolf    schedule 02.07.2013
comment
мммм, что было бы наиболее эффективным средством проверки этого? Я просматриваю свой журнал сборки прямо сейчас, но в нем не указано, как компилятор видит ilDeleteImage(). Однако есть строки, в которых происходит следующее: Found _declspec(dllimport) public: int __cdecl std::basic_streambuf‹char,struct std::char_traits‹char› ›::sputc(char) (__imp? sputc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QEAAHD@Z) Ссылка на dff.obj Ссылка на fft.obj Загруженный msvcprt.lib(MSVCP100.dll)   -  person user2427671    schedule 02.07.2013
comment
добавлена ​​дополнительная информация о журнале сборки   -  person user2427671    schedule 02.07.2013
comment
Для msvc можно использовать переключатель /P для этого .   -  person greatwolf    schedule 02.07.2013
comment
Хорошо, я получил файл .i, и когда я просматриваю его, функции определяются компилятором так, как они должны: пример- __declspec(dllimport) ILuint __stdcall ilCopyPixels(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height , ILuint Depth, ILenum Format, ILenum Type, void *Data);   -  person user2427671    schedule 02.07.2013
comment
Можете ли вы открыть рассматриваемую dll в обходчике зависимостей и перечислить несколько функций, которые она экспортирует, предпочтительно функции, которые не разрешаются? Обратите внимание на то, как на самом деле появляются имена функций.   -  person greatwolf    schedule 02.07.2013
comment
ну, в DevIL.dll одна из перечисленных неразрешимых функций: ilCopyPixels - это то, что говорит для функции в обходчике зависимостей   -  person user2427671    schedule 02.07.2013
comment
Есть ли какие-либо начальные знаки подчеркивания _ или @, добавленные к имени функции?   -  person greatwolf    schedule 02.07.2013
comment
Я также просматривал файлы il.h, ilu.h (файлы .h, в которых объявлены неразрешенные функции), но, похоже, у них есть #ifdef __cplusplus extern C { когда я наводил курсор на __cplusplus, он говорит #define __cplusplus 199711L. Это случайно не повлияет?   -  person user2427671    schedule 02.07.2013
comment
нет, у него нет _ или @ в именах обходчиков зависимостей   -  person user2427671    schedule 02.07.2013
comment
очень подавляющее большинство перечисленных имен не имеют _ или @ на них. Только очень немногие из функций, кажется, имеют это соглашение   -  person user2427671    schedule 02.07.2013
comment
extern "C" предназначен для того, чтобы компилятор С++ не искажал имена функций, и, судя по тому, что вы описали до сих пор, рассматриваемая dll предоставляет интерфейс C. Чего я не понимаю, так это почему ilCopyPixels не имеет extern "C" впереди после предварительной обработки. Или, может быть, весь этот раздел заключен в extern "C" { }?   -  person greatwolf    schedule 02.07.2013
comment
поэтому вы говорите, что при объявлении функция должна была быть предварительно обработана: extern c __declspec(dllimport) ILuint __stdcall ilCopyPixels(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Данные); или что-то вроде этого   -  person user2427671    schedule 02.07.2013
comment
да, но проверьте и убедитесь, что он еще не находится в области блока extern "C" { }.   -  person greatwolf    schedule 02.07.2013
comment
весь раздел закрывается в extern C :в начале файла .h: #ifdef __cplusplus extern C { #endif ближе к концу файла .h: #endif #ifdef __cplusplus }#endif   -  person user2427671    schedule 02.07.2013
comment
кажется, что весь блок объявлений, содержащих функции, находится в области видимости extern C {}, если #ifdef__cplusplus проходит через   -  person user2427671    schedule 02.07.2013
comment
Кажется, проблема в том, что экспортированные функции dll выглядят как __cdecl, но на самом деле являются __stdcall? Если это так, вам может понадобиться файл .def, чтобы исправить символы для поиска во время связывания.   -  person greatwolf    schedule 02.07.2013
comment
меня больше всего беспокоит то, что extern C происходит, если определено __cplusplus, но я нигде не вижу #def __cplusplus, когда ищу решение. Это ненужная забота? Устанавливается ли __cplusplus автоматически, когда он работает в среде С++? или я должен жестко установить это где-то?   -  person user2427671    schedule 02.07.2013
comment
да __cplusplus предопределено при компиляции исходного кода С++.   -  person greatwolf    schedule 02.07.2013
comment
Другой вопрос, заголовки, которые вы включаете, исходят от оригинального автора dll? Включил ли этот автор какие-либо .def файлы в пакет?   -  person greatwolf    schedule 02.07.2013
comment
до сих пор я не изменил ни одной строки кода ни в одном из исходных файлов .h или .cpp. Я работал с тем, что мне дали, и менял конфигурации, чтобы попытаться заставить это работать. в пакете не было файлов .def. Я получил эти файлы с уже собранным проектом, в котором даже был ридми о том, как запустить программу. Я шаг за шагом следил за readme, но создал ошибки связывания, поэтому я там, где я нахожусь в данный момент.   -  person user2427671    schedule 02.07.2013
comment
в ридми, который я получил, в основном говорится, что нужно установить в режиме выпуска, 64, убедиться, что библиотеки, dll находятся в каталоге. Куда поместить все файлы (поскольку путь был задан заранее)   -  person user2427671    schedule 02.07.2013
comment
подождите, так у вас есть исходные файлы, которые использовались для сборки DLL, с которой вы связываетесь? atm, мне в основном интересно, почему экспортированные функции выглядят как __cdecl функции в dll, но заголовок объявляет их как __stdcall соглашение о вызовах. Это разногласие, вероятно, является причиной неразрешенной ошибки.   -  person greatwolf    schedule 02.07.2013
comment
лол, к сожалению, нет. У меня есть файлы .dll и .lib. И у меня есть исходный файл для сборки моего exe с использованием .dll и .lib. Подробные спецификации .dll и .lib для меня остались бы загадкой. Что касается функций экспорта, выглядящих как __cdecl, в то время как заголовок объявляет их как __stdcall, могу ли я просто переключить __cdecl на __stdcall, чтобы разрешить этот конфликт, или создание файла .def является единственным способом разрешить этот возможный конфликт.   -  person user2427671    schedule 02.07.2013
comment
Я, вероятно, должен напечатать более подробный ответ, чтобы охватить все это, но ответ может быть. Вопрос действительно сводится к тому, намеревался ли первоначальный автор использовать __cdecl или __stdcall, потому что они не взаимозаменяемы. Я полагаю, вы можете просто заставить его быть __cdecl, а затем посмотреть, не вылетит ли ваша программа после этого. Вы также можете разобрать одну из функций dll и проверить код очистки в эпилоге функции.   -  person greatwolf    schedule 02.07.2013
comment
хм я с. К сожалению, я не знаю, кто это сделал. Все, что я знаю, это то, что кто-то в прошлом сделал это. Есть еще один человек, который успешно запускал этот код в прошлом (5 месяцев назад) и использовал его для демонстрации продукта, но в настоящее время он находится в командировке. Лично я нахожусь на грани того, чтобы сдаться, и я бы буквально уже сдался, если бы не ваш ответ сегодня. А вот по поводу разборки dll функции. Что я должен искать в частности, что дало бы мне подсказку? Существуют ли деструкторы или что-то, что упоминало бы __cdecl или __stdcall?   -  person user2427671    schedule 02.07.2013
comment
Вы начинаете с выбора экспортированной функции dll, которая принимает один или несколько аргументов. Вы разбираете эту функцию и просматриваете листинг, пока эта функция не вернется. Обычно это выглядит примерно так: mov esp ebp; pop ebp. Ищите приращения к esp, которые указывают на то, что пространство стека освобождается текущей функцией, прежде чем она вернется к вызывающей стороне. Если вы видите, что это происходит, это, вероятно, означает, что это функция __stdcall.   -  person greatwolf    schedule 02.07.2013
comment
Я пытаюсь использовать dumpbin /exports [*].dll, но, похоже, это не дает мне тот тип данных, который вы упомянули. есть ли хорошая альтернатива dumpbin или есть лучшая команда dumpbin, которую я могу использовать для этого?   -  person user2427671    schedule 02.07.2013
comment
ну, я попробовал dumpbin /DISASM для *.dll, но я почти не получаю данных, только 2000 .rsrc, 202000 UPX0, B9000 UPX1   -  person user2427671    schedule 02.07.2013
comment
CFF Explorer может помочь, но мне никогда не приходилось на самом деле находить конкретный функциональный раздел .dll. Двоичный код, реализующий функции, будет находиться в секции .text кстати.   -  person greatwolf    schedule 02.07.2013
comment
В разделе «Каталог экспорта» вы найдете список экспортированных функций. Найдите в столбце Function RVA младший бит адреса. Затем перейдите в раздел «Быстрый дизассемблер», нажмите «Разобрать». Под столбцом адреса прокрутите вниз до адреса, где последние 2 байта соответствуют байтам из RVA функции, которую вы хотите проверить.   -  person greatwolf    schedule 02.07.2013
comment
Хотя отслеживание функций немного сбивает с толку, я не уверен, что делаю это правильно. Но inc esp в инструкции есть   -  person user2427671    schedule 02.07.2013
comment
Для инструкции ret вы видите какое-либо число после нее? Обратите внимание, что вы копаетесь в внутренностях dll нижнего уровня - смотреть на сборку непросто, и это часто сбивает с толку, если вы к этому не привыкли. Так что может быть проще просто скомпилировать, запустить его с __cdecl и посмотреть, не сработает ли он.   -  person greatwolf    schedule 02.07.2013
comment
хорошо, как вы предложили, кажется, что некоторые из неразрешенных функций имеют inc esp, например ilBindImage   -  person user2427671    schedule 02.07.2013
comment
можешь добавить для него pastebin   -  person greatwolf    schedule 02.07.2013
comment
ммм, ладно, я думаю, я просто попробую. Сомневаюсь, что я буду работать. После этого я сдаюсь. Спасибо за помощь, однако, я очень ценю это.   -  person user2427671    schedule 02.07.2013
comment
pastebin.com. для сборки, которую вы видите   -  person greatwolf    schedule 02.07.2013
comment
ILAPI недействительным ILAPIENTRY ilBindImage(ILuint Image);   -  person user2427671    schedule 02.07.2013
comment
pastebin.com/QHUyPaeJ — это сегмент. Хочешь всю сборку?   -  person user2427671    schedule 02.07.2013
comment
ааа, извините, но я должен пересмотреть, я думаю, что неправильно понял функцию адреса или перепутал. обед   -  person user2427671    schedule 02.07.2013
comment
Это определенно выглядит неправильно. Лучше перепроверьте адрес.   -  person greatwolf    schedule 02.07.2013
comment
Хорошо, спасибо за помощь, но я просто решил сдаться и работать над другим проектом. И мой начальник не особо удивился тому, что я не смог найти ответ, так как никогда раньше не работал с dll.   -  person user2427671    schedule 02.07.2013


Ответы (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 в dll. Это предполагает, что файл .def мог использоваться для создания рассматриваемой dll.

Печальное положение дел

К сожалению, соглашение о вызове функций, которому следуют в dll win32, находится в запутанном положении. В стандарте языка 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 аргумента.

person greatwolf    schedule 02.07.2013

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