Для выполнения программного кода Python из скомпилированных программ C.
Расширение играет три основные роли: оптимизация программ — перенос частей программы на язык C порой является единственной возможностью повысить общую производительность; использование существующих библиотек — библиотеки, открытые для использования в Python, получают более широкое распространение; поддержка возможностей в программах Python, не поддерживаемых самим языком непосредственно, — программный код на языке Python обычно не может обращаться к устройствам в абсолютных адресах памяти, например, но может вызывать функции на языке C, способные обеспечить это. Например, ярким представителем расширения в действии является пакет NumPy для Python: обеспечивая интеграцию с оптимизированными библиотеками реализаций численных алгоритмов, он превращает Python в гибкую и эффективную систему программирования вычислительных задач, сопоставимую с Matlab.
Встраи ва ние обычно играет роль подгонки — выполняя программный код Python, подготовленный пользователем, система позволяет модифицировать себя без необходимости полностью пересобирать ее исходный программный код. Например, некоторые программы реализуют промежуточный уровень настройки на языке Python, который может использоваться для подгонки программы по месту за счет изменения программного кода Python. Кроме того, встраивание иногда используется для передачи событий обработчикам на языке Python. Инструменты конструирования графических интерфейсов на языке Python, например, обычно используют прием встраивания для передачи пользовательских событий.
На рис. 20.1 приводится схема этой традиционной двойной модели интеграции. В модели расширения управление передается из Python в программный код на языке C через промежуточный связующий уровень. В модели встраивания программный код на языке C обрабатывает объекты Python и выполняет программный код Python, вызывая функции Python C API. Поскольку в модели расширения Python находится «сверху», он устанавливает определенный порядок интеграции, который можно автоматизировать с помощью таких инструментов, как SWIG — генератор программного кода, с которым мы познакомимся далее в этой главе, воспроизводящий программный код связующего уровня, необходимого для обертывания библиотек C и C++. Поскольку в модели внедрения Python занимает подчиненное положение, при ее использовании именно он предоставляет комплект инструментов API, которые могут использоваться программами C.
В некоторых случаях разделение не такое четкое. Например, используя модуль ctypes, обсуждаемый ниже, сценарии Python могут вызывать библиотечные функции без применения связующего программного кода C. В таких системах, как Cython (и ее предшественнице Pyrex), различия становятся еще более существенными — библиотеки C создаются из комбинации программного кода на языках Python и C. В Jython и Iron- Python используется похожая модель, только язык C в них замещается языками Java и C#, а сама интеграция в значительной мере автоматизирована. Мы познакомимся с этими альтернативами далее в этой главе. А пока сосредоточимся на традиционных моделях интеграции Py- thon/C.
В этой главе мы сначала познакомимся с моделью расширения, а затем перейдем к исследованию основ встраивания. Хотя мы будем рассматривать эти модели в отдельности, следует иметь в виду, что во многих системах обе эти модели комбинируются. Например, встроенный программный код Python, выполняемый из C, может также использовать присоединенные расширения C для взаимодействия с содержащим его приложением. А в системах, основанных на обратных вызовах, библиотеки C, доступные через интерфейсы расширения, в дальнейшем могут использовать технику встраивания для выполнения обработчиков обратного вызова Python.
Например, при создании кнопок с помощью библиотеки tkinter в Python, представленной ранее в этой книге, мы вызывали функции в библиотеке C через прикладной интерфейс расширения. Когда позднее пользователь нажимал эти кнопки, библиотека C реализации инструментов графического интерфейса перехватывала события и передавала их функциям на языке Python, используя модель встраивания. Хотя большая часть деталей скрыта для программного кода Python, тем не менее, в таких системах управление часто свободно передается между языками. Архитектура Python открыта и реентерабельна, что позволяет соединять языки произвольным образом.
Дополнительные примеры интеграции Python/C, не вошедшие в книгу, вы найдете в исходных текстах самого языка Python — его каталоги Modules и Objects являются богатыми источниками информации. Большинство встроенных элементов Python, использованных в этой книге, — от простых, таких как целые числа и строки, до более сложных, вроде файлов, системных вызовов, tkinter и DBM, — используют ту же, представленную выше структуру интеграции. Приемы интеграции, используемые в них, можно изучать по дистрибутиву исходного кода Python и применять при реализации собственных расширений.
Кроме того, руководства «Extending and Embedding» и «Python/C API» содержат достаточно полную информацию и предоставляют сведения, дополняющие эту главу. Если вы планируете использовать приемы интеграции, в качестве следующего шага вам обязательно следует ознакомиться с этими руководствами. Например, в руководствах приводится дополнительная информация о типах расширений на языке C, о применении расширений C в программах с поддержкой многопоточной модели выполнения и о запуске нескольких интерпретаторов в программах, использующих модель встраивания, которую мы в значительной мере опустим здесь.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, II том, 2011