Под Windows, когда я компилирую код C / C ++ в проекте DLL в MSVC, я получаю 2 файла:
MyDll.dll
MyDll.lib
где, насколько я понимаю, MyDll.lib
содержит какую-то таблицу указателей с указанием расположения функций в dll. При использовании этой dll, скажем, в exe-файле, MyDll.lib
он внедряется в exe-файл во время компоновки, поэтому во время выполнения он «знает», где находятся функции, MyDll.dll
и может их использовать.
Но если я скомпилирую тот же код в Linux, я получу только один файл MySo.so
без MySo.a
(эквивалент lib
файла в Linux), так как же исполняемый файл в Linux знает, где находятся функции, MySo.so
если во время компоновки ничего в него не встроено?
Компоновщик MSVC может связывать вместе объектные файлы (.obj) и объектные библиотеки (.lib) для создания .EXE или .DLL.
Чтобы связать с DLL, процесс в MSVC должен использовать так называемую библиотеку импорта (.LIB), которая действует как связующее звено между именами функций C и таблицей экспорта DLL (в DLL функция может быть экспортирована по имени или по порядковому номеру - последний часто использовался для недокументированных API).
Однако в большинстве случаев таблица экспорта DLL имеет все имена функций, и поэтому библиотека импорта (.LIB) содержит в значительной степени избыточную информацию (« функция импорта ABC -> экспортированная функция ABC » и т. Д.).
Можно даже сгенерировать .LIB из существующего .DLL.
Компоновщики на других платформах не имеют этой «функции» и могут напрямую связываться с динамическими библиотеками.
источник
Разница, которую вы видите, заключается в большей степени детализации реализации - под Linux и Windows работают одинаково - вы вызываете функцию-заглушку, которая статически связана в вашем исполняемом файле, и эта заглушка затем загружает DLL / shlib, если необходимо (в случае задержки загрузка , иначе библиотека загружается при запуске программы) и (при первом вызове) разрешает символ через
GetProcAddress
/dlsym
.Единственное отличие состоит в том, что в Linux эти функции-заглушки (которые называются PLT-заглушками) генерируются динамически, когда вы связываете свое приложение с динамической библиотекой (библиотека содержит достаточно информации для их генерации), тогда как в Linux они генерируются, когда сама DLL создано в отдельном
.lib
файле.Эти два подхода настолько похожи, что фактически можно имитировать библиотеки импорта Windows в Linux (см. Проект Implib.so ).
источник
В Linux вы переходите
MySo.so
к компоновщику, и он может извлечь только то, что необходимо для фазы компоновки, добавив ссылку,MySo.so
необходимую во время выполнения.источник
.dll
или.so
являются общими библиотеками (связаны во время выполнения), а.a
и.lib
являются статической библиотекой (связаны во время компиляции). В этом нет разницы между Windows и Linux.Разница в том, как они обрабатываются. Примечание: разница только в таможне, как они используются. Было бы не сложно создать Linux на Windows и наоборот, за исключением того, что практически никто этого не делает.
Если мы используем dll или вызываем функцию даже из нашего собственного двоичного файла, существует простой и понятный способ. Например, в C мы видим, что:
Однако на уровне asm может быть много различий. Например, на x86,
call
код операции выполняется, а42
в стеке. Или в некоторых регистрах. Или где угодно. Никто не знает что до написания dll , как он будет использоваться. Или как проекты захотят использовать это, возможно, написанное с помощью компилятора (или на языке!), Которого сейчас даже не существует (или это неизвестно разработчикам библиотеки dll).Например, по умолчанию C и Pascal помещают аргументы (и получают возвращаемые значения) из стека - но они делают это в другом порядке . Вы также можете обмениваться аргументами между вашими функциями в регистрах путем некоторой - зависимой от компилятора - оптимизации.
Как вы видите правильно, Windows обычай состоит в том, что мы создаем dll, мы также создаем минимальный
.a
/.lib
с ним. Эта минимальная статическая библиотека является только оберткой, символы (функции) этой библиотеки доступны через нее. Это делает необходимые преобразования вызовов уровня asm.Его преимуществом является совместимость. Его недостатком является то, что если у вас есть только .dll, вам может быть трудно понять, как его функции нужно вызывать. Это делает использование dll
.a
хакерской задачей, если разработчик dll не дает вам . Таким образом, он служит, главным образом, в целях закрытости, например, так что легче получить дополнительные деньги для SDK.Другой его недостаток заключается в том, что даже если вы используете динамическую библиотеку, вам нужно статически скомпилировать эту небольшую оболочку.
В Linux бинарный интерфейс dll является стандартным и соответствует соглашению C. Таким образом, нет
.a
необходимости, и существует совместимость двоичных файлов между общими библиотеками, в обмен на что мы не имеем преимуществ обычая Microsoft.источник