Как Python использует файлы DLL без необходимости файла импорта (.lib)?

Я только что закончил урок по созданию DLL-библиотеки. Из руководства я узнал, что DLL также имеет связанный файл lib, который компоновщик будет использовать для статического связывания информации с клиентской программой. Файл lib будет содержать такую ​​информацию, как адреса памяти, где можно найти функции внутри DLL.

Моя путаница возникает при использовании Python. В Python мы, похоже, используем файлы pyd, которые представляют собой файлы в формате DLL с дополнительной информацией, позволяющей вызывать их в Python. Кроме того, я видел примеры кода использования библиотеки ctypes для вызова файлов DLL, что позволяет делать это без использования соответствующего файла lib. Поэтому я не понимаю, зачем нам нужен файл lib при использовании библиотеки DLL в учебнике Microsoft, и почему этот файл, похоже, не используется при вызове библиотек DLL через Python с использованием библиотеки pyd или ctypes.

Убедитесь, что вы не используете .lib в качестве статической библиотеки: stackoverflow.com/a/913744

py660 09.04.2024 02:37

.lib может быть статической библиотекой или библиотекой импорта. См. Файлы DLL и LIB – что и почему?. Импортный .lib не нужен, но тогда API-интерфейсы Win32, такие как LoadLibrary и GetProcAddress, используются для загрузки DLL и адресов функций поиска.

Mark Tolonen 09.04.2024 07:05

@MarkTolonen Как это работает в ситуации, когда мы просто импортируем pyd и не используем ctypes для определения функций DLL?

memelord23 09.04.2024 07:39

.pyd — это DLL с хорошо известной функцией инициализации, которая предоставляет таблицы функций. Для получения более подробной информации прочтите документацию Расширение и внедрение Python. В Python реализована функция import для загрузки DLL и поиска функции устройства.

Mark Tolonen 09.04.2024 08:23
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
104
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Требуется только библиотека импорта DLL (расширение Microsoft .lib). компоновщиком Microsoft для связывания программы с DLL. Это означает конечно, это требуется только во время соединения; это не требуется при время выполнения. Библиотека импорта вообще не имеет функции времени выполнения; это не загружаемый файл.

Кроме того, библиотека импорта требуется только компоновщику Microsoft. по историческим причинам. Технически нет необходимости использовать импорт. библиотека для связывания программы с DLL. MYSY2 / MinGW-w64 компоновщику, вызываемому Windows GCC, не нужны библиотеки импорта: он может ссылаться напрямую против DLL, хотя он также может использовать библиотеку импорта, если обнаружит один первый.

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

Вот некоторые имена символов symbol1, symbol2,...,symbolN, которые не могут быть определены любые обычные объектные файлы, доступные для связи, но определенные в DLL name.dll.

Обычно symbol1, symbol2,...,symbolN — это имена функций, экспортируемых name.dll. Компоновщик извлекает эти небольшие объектные файлы из архива и связывает их. информацию статически в программу. Затем во время выполнения компоновщик времени выполнения обнаружит эту информацию, когда его попросят загрузить программу; это будет найдите путь к библиотеке времени выполнения для name.dll и - в случае успеха - он будет загрузить name.dll в адресное пространство программы и разрешить программу ссылки на symbol1, symbol2,...,symbolN на определения, которые (надеюсь) предоставлено name.dll. Если это тоже успешно (для всех DLL, которые программа потребности) программа, наконец, может быть запущена. Роль библиотеки импорта в жизни программы завершается, как только статический компоновщик создал программу.

Этот процесс получения информации о DLL, от которой зависит программа, и о символы, на которые ссылается программа, определенные в DLL, и статически связывающие это информацию в программу в виде инструкций для компоновщика среды выполнения — это то, что мы имеется в виду путем связывания с DLL.

Как уже отмечалось, для выполнения этого процесса нет необходимости использовать библиотеку импорта. Импортировать библиотеки — это способ Microsoft сделать это. В Linux и других ОС Python работает на всех из них. библиотеки импорта вообще не используются для связывания с динамическими библиотеками. Вместо этого сама динамическая библиотека является входными данными для статического компоновщика. Динамическую библиотеку нельзя скомпоновать статически, но компоновщик просто проверяет его, чтобы увидеть, какие неопределенные символы в программе определены динамической библиотекой, а затем статически связывает необходимые инструкции с компоновщиком времени выполнения в программе.

Мало того, что библиотека импорта не нужна, также нет необходимости статически связывать любую информацию. about name.dll в программу, чтобы программа могла загружать name.dll и вызывать в ней функции. Если программа считает, что name.dll существует в системе, и хочет сослаться на символ он считает, что определена в name.dll (обычно вызывает функцию, определенную в name.dll), он сам может запросить ОС, чтобы найти и загрузить name.dll, используя LoadLibrary системный вызов и запросите компоновщик времени выполнения, чтобы дать ему адрес символа, который он хочет ссылка из name.dll, используя GetProcAddress системный вызов.

Итак, процесс статического связывания инструкций компоновщика времени выполнения в программу - будь то это делается с использованием библиотеки импорта или нет - это способ, с помощью которого вы можете избежать программного связывания DLL во время выполнения и вместо этого сделать все это операционной системой при запуске программы. И библиотека импорта — это дополнительный способ избежать этого.

Python, конечно же, является интерпретатором времени выполнения. Он вообще не вызывает статический компоновщик. Если вы попросите его импортировать ваш модуль .pyd, Python загрузит DLL программно. Если вы используете cytypes для звонка DLL C или C++, Python либо загружает DLL программно, либо вы можете самостоятельно загрузить его программно, вызвав cdll.LoadLibrary(libname).

Любая DLL, которую Python необходимо загрузить либо для своих целей, либо для целей пользователя, является либо DLL, которую он загружает. программно, или это DLL, с которой Python был связан при сборке Python, и которая будет автоматически загружен Python. В любом случае, как пользователю Python, вам никогда не понадобится библиотека импорта для этой DLL, и это истинно независимо от того, вызываете ли вы Python с помощью команды оболочки > python3 myscript.py или вызываете он встроен в программу C или C++, связанную с [lib]python3dll.

Спасибо за ответ. Хотя я не совсем придерживаюсь этой линии, An import library name.lib serves the linker as a statically linkable proxy for name.dll, which itself cannot be statically linked. У меня сложилось впечатление, что объектные файлы изнутри name.lib были статически связаны с программой. Эти объектные файлы будут содержать адреса памяти символов внутри name.dll.

memelord23 14.04.2024 01:13

Ваше впечатление верное. Объектный файл в библиотеке импорта сопоставляет имя символа с его относительным адресом в DLL. Эти данные позволяют компоновщику времени выполнения определить реальный адрес символа во время выполнения, если он сможет найти и загрузить DLL. Эти объектные файлы статически связываются с программами во время сборки, поскольку сама DLL не может быть статически связана с программами. У вас может быть адрес моего дома на листке бумаги в кармане: это заместитель моего дома: у вас в кармане не будет никакой части моего дома. «Статически связан в программе» = «физически в программе».

Mike Kinghan 14.04.2024 09:18

о, я понимаю, я думал, что под which itself cannot be statically linked вы имели в виду, что он не связан статически с программой, но теперь ваш комментарий проясняет это с помощью These object files are are statically linked into programs at buildtime. Ваше здоровье.

memelord23 14.04.2024 14:27

Другие вопросы по теме