Связывание с файлом DLL может происходить неявно при компиляции время ссылки или явно во время выполнения.В любом случае, DLL в конечном итоге загружается в пространство памяти процессов, и все ее экспортированные точки входа доступны приложению.
Если явно используется во время выполнения, вы используете LoadLibrary()
и GetProcAddress()
длявручную загрузите DLL и получите указатели на функции, которые нужно вызвать.
Если неявно связаны при сборке программы, то заглушки для каждого экспорта DLL, используемого программой, связываются с программой из библиотеки импорта, и эти заглушки обновляются по мере загрузки EXE и DLL, когдапроцесс запускается.(Да, я немного упростил здесь ...)
Эти заглушки должны быть откуда-то, и в цепочке инструментов Microsoft они происходят из специальной формы файла .LIB, называемого библиотека импорта .Требуемая .LIB обычно создается в то же время, что и DLL, и содержит заглушку для каждой функции, экспортируемой из DLL.
Смущает, что статическая версия той же библиотеки также будет поставляться как .LIBфайл.Нет тривиального способа отличить их, за исключением того, что LIB, которые являются библиотеками импорта для DLL, обычно будут меньше (часто намного меньше), чем соответствующие статические LIB.
Если вы используете цепочку инструментов GCC, случайновам на самом деле не нужны библиотеки импорта для соответствия вашим DLL.Версия компоновщика Gnu, перенесенная в Windows, напрямую понимает библиотеки DLL и может синтезировать большинство любых необходимых заглушек на лету.
Обновление
Если вы просто не можете устоять, зная, где все гайки иБолты действительно есть, и что действительно происходит, в MSDN всегда есть что-то, чтобы помочь.Статья Мэтта Пьетрека Углубленный взгляд на формат исполняемого файла Win32 представляет собой очень полный обзор формата файла EXE и его загрузки и запуска.Его даже обновили, чтобы он охватывал .NET и даже больше, так как он первоначально появился в журнале MSDN ca.2002.
Кроме того, может быть полезно узнать, как точно узнать, какие библиотеки DLL используются программой.Инструмент для этого - Зависимость Уокер, она же зависит от.exe.Его версия включена в Visual Studio, но последняя версия доступна от ее автора по адресу http://www.dependencywalker.com/.. Она может идентифицировать все библиотеки DLL, которые были указаны во время соединения (как при ранней загрузке, так и при задержке загрузки), и можеттакже запустите программу и просмотрите все дополнительные библиотеки DLL, которые она загружает во время выполнения.
Обновление 2
Я переписал часть предыдущего текста, чтобы уточнить его при повторном чтении и использоватьУсловия подразумевают и явное связывание для согласованности с MSDN.
Итак, у нас есть три способа сделать библиотечные функции доступными для использования программой.Тогда возникает очевидный вопрос: «Как выбрать какой путь?»
Статическое связывание - это то, как основная часть самой программы связана. Все ваши объектные файлы перечислены и собраны вместе в EXE-файл компоновщиком. Попутно компоновщик позаботится о мелких делах, таких как исправление ссылок на глобальные символы, чтобы ваши модули могли вызывать функции друг друга. Библиотеки также могут быть статически связаны. Объектные файлы, которые составляют библиотеку, собираются библиотекарем в файл .LIB, который компоновщик ищет модули, содержащие необходимые символы. Одним из эффектов статического связывания является то, что с ним связаны только те модули из библиотеки, которые используются программой; другие модули игнорируются. Например, традиционная математическая библиотека C включает в себя множество функций тригонометрии. Но если вы ссылаетесь на него и используете cos()
, вы не получите копию кода для sin()
или tan()
, если только вы не вызвали эти функции. Для больших библиотек с богатым набором функций это выборочное включение модулей важно. На многих платформах, таких как встроенные системы, общий размер кода, доступного для использования в библиотеке, может быть большим по сравнению с пространством, доступным для хранения исполняемого файла на устройстве. Без выборочного включения было бы сложнее управлять деталями создания программ для этих платформ.
Однако наличие копии одинаковой библиотеки в каждой запущенной программе создает нагрузку на систему, которая обычно запускает множество процессов. При правильной системе виртуальной памяти страницы памяти, имеющие одинаковое содержимое, должны существовать в системе только один раз, но могут использоваться многими процессами. Это создает преимущество для повышения вероятности того, что страницы, содержащие код, вероятно, будут идентичны какой-либо странице в максимально возможном количестве других запущенных процессов. Но если программы статически связываются с библиотекой времени выполнения, то каждая из них имеет различное сочетание функций, каждая из которых размещена на карте памяти процессов в разных местах, и не так много разделяемых кодовых страниц, если только это не программа, которая сама по себе является работать больше, чем процесс. Таким образом, идея DLL получила еще одно важное преимущество.
DLL для библиотеки содержит все ее функции, готовые для использования любой клиентской программой. Если многие программы загружают эту DLL, они могут поделиться ее кодовыми страницами. Все побеждают. (Ну, пока вы не обновите DLL новой версией, но это не является частью этой истории. Google DLL Hell для этой стороны рассказа.)
Таким образом, первый большой выбор, который нужно сделать при планировании нового проекта, это между динамической и статической связью. Благодаря статическому связыванию у вас будет меньше файлов для установки, и вы не будете защищены от обновления сторонней DLL, которую вы используете. Тем не менее, ваша программа больше, и она не так хороша в экосистеме Windows. Благодаря динамическому связыванию у вас есть больше файлов для установки, у вас могут быть проблемы с обновлением сторонней DLL, которую вы используете, но вы, как правило, дружелюбнее к другим процессам в системе.
Большим преимуществом DLL является то, что она может быть загружена и использована без перекомпиляции или даже перекомпоновки основной программы. Это может позволить стороннему поставщику библиотеки (например, Microsoft и среда выполнения C) исправить ошибку в своей библиотеке и распространить ее. После того как конечный пользователь установит обновленную DLL, он сразу же получит выгоду от исправления этой ошибки во всех программах, которые используют эту DLL. (Если это не сломает вещи. См. DLL Ад.)
Другое преимущество заключается в различии неявной и явной загрузки. Если вы перейдете к дополнительным усилиям по явной загрузке, то DLL, возможно, даже не существовало, когда программа была написана и опубликована. Это позволяет использовать механизмы расширения, которые могут обнаруживать и загружать плагины, например.