Как написать dll на python

Обновлено: 05.07.2024

Какой самый простой способ использовать DLL файл изнутри Python ?

В частности, как это можно сделать без написания какого-либо дополнительного C++ кода- обертки, чтобы раскрыть функциональность Python ?

Собственная Python функциональность настоятельно предпочтительнее, чем использование сторонней библиотеки.

@Remuze вы пометили неправильный вопрос или пометить неправильный ответ? Они оба питоны, но я не вижу причин, почему вы могли бы найти их похожими (и я проверил историю изменений, чтобы убедиться, что она не была как-то ближе в какой-то момент в прошлом) @foon хммм да извините, я хотел пометить другой вопрос как дубликат и поставить этот :) Я думаю, это показывает, насколько они похожи!

Для простоты использования, ctypes это путь.

Следующий пример ctypes взят из реального кода, который я написал (в Python 2.5). Это, безусловно, самый простой способ, который я нашел для выполнения того, что вы просите.

ctypes Материал имеет все типы С-типа данных ( int , char , short , void* , и т.д.) и может передавать по значению или ссылке. Он также может возвращать определенные типы данных, хотя мой пример этого не делает (HLL API возвращает значения путем изменения переменной, переданной по ссылке).

С точки зрения конкретного примера, показанного выше, EHLLAPI от IBM представляет собой довольно непротиворечивый интерфейс.

Все вызовы проходят четыре пустых указателя (EHLLAPI отправляет код возврата через четвертый параметр, указатель на int so, хотя я указываю int в качестве типа возврата, я могу смело его игнорировать) согласно документации IBM здесь . Другими словами, вариант C функции будет:

Это делает единственную простую ctypes функцию, способную делать все, что обеспечивает библиотека EHLLAPI, но вполне вероятно, что другим библиотекам потребуется отдельная ctypes функция, настроенная для каждой библиотечной функции.

Возвращаемое значение from WINFUNCTYPE является прототипом функции, но вам все равно нужно настроить дополнительную информацию о параметрах (помимо типов). Каждый кортеж hllApiParams имеет параметр "direction" (1 = вход, 2 = выход и т. Д.), Имя параметра и значение по умолчанию - подробности см. В ctypes документе

Когда у вас есть прототип и информация о параметрах, вы можете создать Python, «вызываемый» hllApi для вызова функции. Вы просто создаете необходимую переменную ( p1 через p4 в моем случае) и вызываете функцию с ними.

image

Недавно меня заинтересовала тема использования DLL из Python. Кроме того было интересно разобраться в их структуре, на тот случай, если придется менять исходники библиотек. После изучения различных ресурсов и примеров на эту тему, стало понятно, что применение динамических библиотек может сильно расширить возможности Python. Собственные цели были достигнуты, а чтобы опыт не был забыт, я решил подвести итог в виде статьи — структурировать свой знания и полезные источники, а заодно ещё лучше разобраться в данной теме.

Под катом вас ожидает статья с различными примерами, исходниками и пояснениями к ним.

Содержание

  • Структура DLL
  • DLL & Python
    • Подключение DLL
    • Типы данных в С и Python
    • Аргументы функция и возвращаемые значения
    • Своя DLL и ее использование

    Надеюсь из содержания немного станет понятнее какую часть нужно открыть, чтобы найти ответы на свои вопросы.

    Структура DLL

    DLL — Dynamic Link Library — динамическая подключаемая библиотека в операционной системе (ОС) Windows. Динамические библиотеки позволяют сделать архитектуру более модульной, уменьшить количество используемых ресурсов и упрощают модификацию системы. Основное отличие от .EXE файлов — функции, содержащиеся в DLL можно использовать по одной.

    Учитывая, что статья не о самих библиотеках, лучше просто оставить здесь ссылку на довольно информативную статью от Microsoft: Что такое DLL?.

    Для того, чтобы понять, как использовать динамические библиотеки, нужно вникнуть в их структуру.

    DLL содержит набор различных функций, которые потом можно использовать по-отдельности. Но также есть возможность дополнительно указать функцию точки входа в библиотеку. Такая функция обычно имеет имя DllMain и вызывается, когда процессы или потоки прикрепляются к DLL или отделяются от неё. Это можно использовать для инициализации различных структур данных или их уничтожения.

    Рисунок 1 — Пустой template, предлагаемый Code Blocks для проекта DLL.

    На рисунке 1 приведен шаблон, который предлагает Code Blocks, при выборе проекта типа DLL. В представленном шаблоне есть две функции:

    Для начала стоит подробнее рассмотреть функцию DllMain . Через нее ОС может уведомлять библиотеку о нескольких событиях (fdwReason):

    DLL_PROCESS_ATTACH – подключение DLL. Процесс проецирования DLL на адресное пространство процесса. С этим значением DllMain вызывается всякий раз, когда какой-то процесс загружает библиотеку с явной или неявной компоновкой.

    DLL_PROCESS_DETACH – отключение DLL от адресного пространства процесса. С этим значением DllMain вызывается при отключении библиотеки.

    DLL_THREAD_ATTACH – создание процессом, подключившим DLL, нового потока. Зачем DLL знать о каких-то там потоках? А вот зачем, далеко не каждая динамическая библиотека может работать в многопоточной среде.

    DLL_THREAD_DETACH – завершение потока, созданного процессом, подключившим DLL. Если динамическая библиотека создает для каждого потока свои "персональные" ресурсы (локальные переменные и буфера), то это уведомление позволяет их своевременно освобождать.

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

    У DllMain не так много аргументов, самый важный fdwReason уже рассмотрен выше, теперь о двух других:

    • Аргумент lpvReserved указывает на способ подключения DLL:
      • 0 — библиотека загружена с явной компоновкой.
      • 1 — библиотека загружена с неявной компоновкой.

      О явной и неявной компоновке можно прочесть подробно в статье: Связывание исполняемого файла с библиотекой DLL.

      В предложенном на рисунке 1 шаблоне есть функция SomeFunction , которая может быть экспортирована из динамической библиотеки. Для того, чтобы это показать, при объявлении функции указывается __declspec(dllexport) . Например, так:

      Функции, не объявленные таким образом, нельзя будет вызывать снаружи.

      DLL & Python

      Первым делом, расскажу, как подключать уже собранные DLL, затем, как вызывать из них функции и передавать аргументы, а уже после этого, постепенно доделаю шаблон из Code Blocks и приведу примеры работы с собственной DLL.

      Подключение DLL

      Основной библиотекой в Python для работы с типами данных, совместимыми с типами языка С является ctypes . В документации на ctypes представлено много примеров, которым стоит уделить внимание.

      Чтобы начать работать с DLL, необходимо подключить библиотеку к программе на Python. Сделать это можно тремя способами:

      • cdll — загружает динамическую библиотеку и возвращает объект, а для использования функций DLL нужно будет просто обращаться к атрибутам этого объекта. Использует соглашение вызовов cdecl.
      • windll — использует соглашение вызовов stdcall. В остальном идентична cdll.
      • oledll — использует соглашение вызовов stdcall и предполагается, что функции возвращают код ошибки Windows HRESULT. Код ошибки используется для автоматического вызова исключения WindowsError.

      Для первого примера будем использовать стандартную Windows DLL библиотеку, которая содержит всем известную функцию языка С — printf() . Библиотека msvcrt.dll находится в папке C:\WINDOWS\System32 .

      Код Python:

      Результат:

      Можно использовать подключение библиотеки с помощью метода windll либо oledll , для данного кода разницы не будет, вывод не изменится.

      Если речь не идет о стандартной библиотеке, то конечно следует использовать вызов с указанием пути на dll. В ctypes для загрузки библиотек предусмотрен метод LoadLibrary . Но есть еще более эффективный конструктор CDLL , он заменяет конструкцию cdll.LoadLibrary . В общем, ниже показано два примера вызова одной и той же библиотеки msvcrt.dll.

      Код Python:

      Иногда случается, что необходимо получить доступ к функции или атрибуту DLL, имя которого Python не "примет"… ну бывает. На этот случай имеется функции getattr(lib, attr_name) . Данная функция принимает два аргумента: объект библиотеки и имя атрибута, а возвращает объект атрибута.

      Код Python:

      Результат:

      Теперь становится понятно, как подключить библиотеку и использовать функции. Однако, не всегда в DLL нужно передавать простые строки или цифры. Бывают случаи, когда требуется передавать указатели на строки, переменные или структуры. Кроме того, функции могут и возвращать структуры, указатели и много другое.

      Типы данных в С и Python

      Модуль ctypes предоставляет возможность использовать типы данных совместимые с типами в языке С. Ниже приведена таблица соответствия типов данных.

      Сtypes type C type Python type
      c_bool _Bool bool (1)
      c_char char 1-character string
      c_wchar wchar_t 1-character unicode string
      c_byte char int/long
      c_ubyte unsigned char int/long
      c_short short int/long
      c_ushort unsigned short int/long
      c_int int int/long
      c_uint unsigned int int/long
      c_long long int/long
      c_ulong unsigned long int/long
      c_longlong __int64 or long long int/long
      c_ulonglong unsigned __int64 or unsigned long long int/long
      c_float float float
      c_double double float
      c_longdouble long double float
      c_char_p char * (NUL terminated) string or None
      c_wchar_p wchar_t * (NUL terminated) unicode or None
      c_void_p void * int/long or None

      Таблица 1 — Соответствие типов данных языка Python и языка C, которое предоставляет модуль ctypes .

      Первое, что стоит попробовать — это использовать указатели, куда без них? Давайте напишем программу, где создадим строку и указатель на неё, а потом вызовем printf() для них:

      Результат:

      Если вы создали указатель, то разыменовать (получить доступ к значению, на которое он указывает) можно с использованием атрибута value , пример выше.

      Аргументы функций и возвращаемые значения

      По умолчанию предполагается, что любая экспортируемая функция из динамической библиотеки возвращает тип int . Другие возвращаемые типы можно указать при помощи атрибута restype . При этом, чтобы указать типы аргументов функции можно воспользоваться атрибутом argtypes .

      Например, стандартная функция strcat принимает два указателя на строки и возвращает один указатель на новую строку. Давайте попробуем ей воспользоваться.

      Код Python:

      Результат:

      На этом закончим с примерами использования готовых DLL. Давайте попробуем применить знания о структуре DLL и модуле ctypes для того, чтобы собрать и начать использовать собственную библиотеку.

      Своя DLL и ее использование

      Пример 1

      Шаблон DLL уже был рассмотрен выше, а сейчас, когда дело дошло до написания своей DLL и работы с ней, выскочили первые и очевидные грабли — несовместимость разрядности DLL и Python. У меня на ПК установлен Python x64, оказалось, что как бы не были DLL универсальны, разрядность DLL должна соответствовать разрядности Python. То есть, либо ставить компилятор x64 и Python x64, либо и то и то x32. Хорошо, что это не сложно сделать.

      Ниже привожу код шаблона DLL, в который добавил вывод строки при подключении библиотеки, а также небольшой разбор и вывод аргументов, с которыми вызвалась DllMain . В примере можно понаблюдать, какие участки кода библиотеки вызываются и когда это происходит.

      Код DLL на С:

      Код Python:

      Функция SomeFunction получает указатель на строку и выводит её в окно. На рисунке ниже показана работа программы.




      Рисунок 2 — Демонстрация работы шаблона библиотеки из Code Blocks.

      Все действия происходящие в кейсе DLL_PROCESS_ATTACH , код которого приведен ниже, вызываются лишь одной строкой в Python коде:



      Рисунок 3 — Действия происходящие при подключении DLL.

      Пример 2

      Чтобы подвести итог по использованию DLL библиотек из Python, приведу пример, в котором есть начальная инициализация параметров и передача новых через указатели на строки и структуры данных. Этот код дает понять, как написать аналог структуры С в Python. Ниже привожу код main.c , man.h и main.py .

      Код DLL на С:

      В коде main.h определена структура Passport с тремя полями: два указателя и целочисленная переменная. Кроме того, четыре функции объявлены, как экспортируемые.

      Код DLL на С:

      Внутри кейса DLL_PROCESS_ATTACH происходит выделение памяти под строки и начальная инициализация полей структуры. Выше DllMain определены функции:

      GetPassport — вывод полей структуры passport в консоль.

      *SetName(char new_name)** — установка поля name структуры passport .

      *SetSurname(char new_surname)** — установка поля surname структуры passport .

      *SetPassport(Passport new_passport)** — установка всех полей структуры passport . Принимает в качестве аргумента указатель на структуру с новыми полями.

      Теперь можно подключить библиотеку в Python.

      Код на Python

      В коде выше многое уже знакомо, кроме создания структуры аналогичной той, которая объявлена в DLL и передачи указателя на эту структуру из Python в DLL.

      Скажите можно ли и как создать dll средствами Python?

      создание dll в Python

      никак средствами питона.

      создание dll в Python

      а какими внешними средствами можно создать dll из python-кода под win xp?

      создание dll в Python

      Никакими. dll пишутся на компилируемых языках.

      создание dll в Python

      переформулирую вопрос:
      есть знание языка Python, а хочется создать dll. что можно сделать?

      создание dll в Python

      Если код на cython (именно cython, а не cpython) транслируется в код на C, а затем компилируется, например, gcc, то можешь.

      Вопрос: зачем тебe dll, если ты не можешь написать ее на компилируемых языках?

      Отредактировано (Янв. 6, 2010 18:04:18)

      создание dll в Python

      axe
      есть знание языка Python, а хочется создать dll. что можно сделать?

      создание dll в Python

      создание dll в Python

      expee, у меня задача сделать helloworld.dll
      потом буду разбираться, как вызвать упакованную функциональность из python.

      я поставил MinGW-5.1.6.exe и Cython-0.11.2.win32-py2.5.exe
      далее делаю по туториалу,
      только вызываю чуть по-другому:

      т.к. с –inplace работать не хочет

      создаётся файл helloworld.c и папка build с таким содержанием:
      - /lib.win32-2.5
      – helloworld.pyd
      - /temp.win32-2.5
      – /Release
      — helloworld.def
      — helloworld.o

      если запустить консоль python в той же папке, где лежит helloworld.pyd, то можно делать import helloworld. круто, только не знаю, что это даёт.

      пробовал компилировать helloworld.c командами:
      gcc helloworld.c -o helloworld.exe
      и
      cpp helloworld.c -o helloworld.exe

      и то и другое приводит к ошибкам. в случае gcc - ошибок на два экрана, наверное, при cpp - строк 5.
      в-общем, что надо делать с helloworld.c не знаю.

      создание dll в Python

      Смысла упаковывать функции в dll, а затем использовать сторонние библиотеки для доступа к этой dll нет. Это глупо и непрактично. В тех же *nix-like системах твоя программа работать уже не будет. С твоими знаниями и нежеланием читать документацию, а так-же искать что-то, ты врятли добьешься того, чего хочешь.

      Если тебе просто дали задание написать dll'ку, то пиши на си или, например, ассемблере.

      Возможно ли написать библиотеку dll, которая будет открывать окно браузера во время игры?
      Возможно ли написать на Delphi библиотеку dll, которая будет открывать окно браузера во время игры?

      Создать DLL-библиотеку, которая содержит математические методы
      Создать DLL-библиотеку, которая содержит математические методы для вычисления целой части числа.

      Возможно ли сделать из программы библиотеку dll?
      Собственно, возможно ли какими-то способами сделать уже из готового приложения библиотеку dll?

      Создать библиотеку dll
      Здравствуйте. Java-разработчик, не сишник, но нужно немного поработать с оборудованием. У этого.

      Не знаю, что такое mql.
      Для С++ можно, но на сишной стороне надо будет использовать Python.h, т. е. специально адаптировать сишную часть. Но вообще неправильный подход, питон не для длл-ок. Для длл-ок следует использовать С++ и прочий натив.

      Добавлено через 21 секунду
      Гуглить Python/C API.

      Есть нужда в обработке имён функций и создании массивов, С++ не обладает такими гибкими возможностями, спасибо за советы.

      Nexi99, не понял, что за обработка имён функций имеется в виду, но всё равно это не отменяет моего замечания.

      Если у вас большое приложение на плюсах и надо небольшой кусочек вынести в питон, то используется Python embedding. Вот это уже да, штатная операция.

      Спасибо за информацию, если доживу то буду это всё использовать. Для С++ можно, но на сишной стороне надо будет использовать Python.h, т. е. специально адаптировать сишную часть. Если адаптировать Python.h на сишной стороне, то этот код откомпилируется и будет работать напрямую с процессором как стандартный сишный код или он так и останется текстом и будет происходить постоянная трансляция между Python и с++? Адаптировать Python.h не надо, он поставляется разработчиками питона. Адаптировать надо вашу сишную часть, чтобы она использовала Python.h.
      Внутри ваш сишный код, конечно, будет работать как стандартный сишный код - он же сишный код. Насчёт трансляции не понял. Адаптировать надо вашу сишную часть, чтобы она использовала Python.h.
      Внутри ваш сишный код, конечно, будет работать как стандартный сишный код - он же сишный код. Всё понятно спасибо.
      Насчёт трансляции - я имел ввиду что будет происходить постоянное чтение скрипта/текста преобразование его в с++, а если вы пишите что этот код становится одним единым с сишным когда подключаешь Python.h к с++ то это в корне меняет дело. Nexi99, питоновский код "транслируется" в штатном порядке, как питоновский. (На самом деле он не транслируется, но для простоты скажем так.)
      Насчет "становится единым" - не совсем. Просто питоновский код сможет вызывать ваш сишный. Точно также, как он вызывает другой, "свой" сишный - например, внутренности списков.

      Человеку наоборот надо из С++ вызывать питон.

      ТС, там по факту вшивается интерпретатор питона. Пример: На сколько сложно перевести код Python на Си?

      Не а. Это трейдерский язык программирования a-la Си, только проще.

      Вот только ТС этого не понимает. Он думает что можно написать на Python скрипт, превратить его в обычную dll (не Python pyd) и потом пользоваться в С++. Наверное, можно и dll-ку скомпилить. Только она будет работать со скоростью питона, то есть никак. Вот только ТС этого не понимает. Он думает что можно написать на Python скрипт, превратить его в обычную dll (не Python pyd) и потом пользоваться в С++.

      Я уже разобрался благодаря вам конечно, что скомпилировать Пион не получиться.

      Добавлено через 7 минут

      Добавлено через 2 часа 11 минут

      Скажите а как читаются dll библиотеки(например сишные), подключенные к основной программе как бинарные файлы или как скрипты (происходит постоянный поиск указанной функции), ведь по сути динамическая dll подключенная к основной программе не компилируется а ошибки вылетают только тогда когда сама программа запущена а не в момент компиляции, возникает много вопросов как это всё работает. Библиотека - она есть библиотека. Есть заголовки функций, в dll - сама скомпилированная функция. И при вызове функции можно уронить программу. Скажите а как читаются dll библиотеки(например сишные), подключенные к основной программе как бинарные файлы или как скрипты Что из себя представляет "основная программа"? Бинарные файлы и скрипты - это большая разница. Nexi99, У меня к вам пара вопросов.
      На этот форум регулярно приходят люди с вопросами, типа, как что-то прикрутить к mql, как что-то в этом mql-е сделать итд. Вот, соответственно, первый вопрос: Вы можете написать компилятор, или хотя бы транслятор своего языка по типу этого mql?
      То есть люди написали этот mql. Написали кучу гайдов, как создать своего торгового бота и получать стопицот милиардов баксов в день ничего не делая, сами написание этого бота ниасилили? Если асилили, то почему они не молчат об этом, тупо гребя свое бабло? Почему они с вами решили поделиться? Почему вы считаете что они намного тупее вас, учитывая, что они таки написали этот mql?
      И самый главный вопрос: как вы, блжад, на это ведетесь? Вы можете написать компилятор, или хотя бы транслятор своего языка по типу этого mql?
      То есть люди написали этот mql. Написали кучу гайдов, как создать своего торгового бота и получать стопицот милиардов баксов в день ничего не делая, сами написание этого бота ниасилили? Если асилили, то почему они не молчат об этом, тупо гребя свое бабло? Почему они с вами решили поделиться? Почему вы считаете что они намного тупее вас, учитывая, что они таки написали этот mql?
      И самый главный вопрос: как вы, блжад, на это ведетесь? Могу писать но у меня жизни не хватит на это эти оболочки и весь функционал долго строится. Но почему-то исходного кода от mql4 нет, как же мне модифицировать его, только писать свой компилятор или библиотеки. Кто неасилил написание бота я? Это дело большого времени, печи да и всё в чём проблема. Об этом умалчивают и очень хорошо. Кто со мной чем поделился, если бы поделился меня бы здесь не было. Я писал что они тупее, может и писал может и тупее что изменилось. Я пишу своего робота влаживая(очень большую) частицу себя. Возникает вопрос а языки программирования тоже ведь для маркетинга придумали правильно. Могу писать но у меня жизни не хватит на это эти оболочки и весь функционал долго строится. Ну и? Они, тупые, писали это чтоб ты обогатился? Сами-то они без тебя, конечно, грамотного робота не напишут. Вот на то, на что у тебя жизни не хватит у них времени хватило, а на робота. ну тупые они, без тебя никак.
      Да, это тайна за семью замками. Никто не знает. Только ты. Всех остальных в гугле забанили. Поэтому ты пришел на форум с тривиальным вопросом. Вот бы мне нагуглить как создать торгового робота и обогатиться за три секунды. Но, видишь ли, я, наверное, тупой. Вот, написать любой другой софт, где нужна определенная квалификация, я могу. А торгового робота. ну куда мне. Это только ты можешь. Поэтому ты пришел на форум с тривиальным вопросом. Вот бы мне нагуглить как создать торгового робота и обогатиться за три секунды. Где я писал о том что можно написать робота за 3 с., а также о том как его написать, всему учился сам. Ни в одной из моих тем не было упоминания о подобном. Это очень простой софт. Придумать что-то проще сложно.
      Да. Потому что идти некуда. Это тупик. Проще "заработать" играя в казино.
      Это вполне корректно. Я писал о явлении торговых роботов как таковом. Может быть мои посты спасут кого-нибудь, в чью голову придет такая идея, но кто еще способен здраво ее осмыслить.

      Возможно ли создать полностью встраиваемую бинарную библиотеку на C++?
      Эм. Да, я не знаю/придумал, как именно назвать эту "встраиваемость". Речь идет о линковке со.

      Как создать dll библиотеку
      Не могу разобраться как зоздать библиотеку ! Захожу в File->New project->Consol Application Win32->.

      Пытаюсь создать и подключить dll библиотеку
      Здравствуйте, всем. Пытаюсь создать и подключить dll библиотеку. Понимаю, что вопрос кажется.


      [WPF] Создать dll библиотеку из приложения windows
      Создал приложение Windows WPF. Запускается отлично, без ошибок. Потом понял, что нужно из этого.


      Как создать dll библиотеку из файла заголовка
      прошу, сильно не кидайтесь кирпичами, за незнанием с++ пришлось прибегнуть к вашей помощи, имеется.

      Читайте также: