Единственный весомый недостаток питона, с которым я столкнулся - его невысокая производительность. Всем известно, что узкое горло производительности в решениях на питоне во многом решается C/C++ расширениями. Эта статья о моих экспериментах в этой области. Для меня были очевидны три способа расширения функциональности Python на платформе win32:
- Создание модуля Python написанного на С/С++ (родной и мульти-платформенный подход)
- Импорт win32 функций из DLL для windows (удобный подход, можно вызывать как и стандартные API функции так и собственные)
- Взаимодействие со стандартными (или) самописными COM объектами
Итак, по порядку:
- Инструменты для написания / сборки и их настройка
Ввиду того, что всё что я делал до сих пор касается платформы win32, вся информация о конфигурировании относится к Windows 7 x64 и Python 2.7. Для написания модуля расширения мне пришлось использовать обыкновенный текстовый редактор, командную строку Windows и MinGW (Minimalist GNU for Windows).
Начнем с установки и настройки MinGW. Загружаем MinGW с официального сайта переходим в раздел Downloads и загружаем последнюю версию MinGW (Automated MinGW Installer). Устанавливаем MinGW по-умолчанию в C:\MinGW\ и прописываем переменные окружения. Для указания переменных окружения открываем Controle panel -> System -> Advanced system settings в открывшемся окне (System properties) выбираем вкладку Advanced и нажимаем кнопку Environment Variables. Далее в открывшемся окне (Environment Variables) в таблице System variables выбираем переменную с именем Path, нажимаем Edit и прописываем в Variable value путь к компилятору "C:\MinGW\bin". На этом установка MinGW завершена.
- Создание модуля Python написанного на С/С++ (родной и мульти-платформенный подход)
В обзорных целях нужно обратить внимание не то, что реализация стандартного CPython из коробки поддерживает создание модулей расширения на C/C++. И в документации об этом сказано и примеры доступны так же. Однако есть одно НО. На каждой из поддерживаемых платформ наверняка существует специфика подобной реализации. Так как мои изыскания лежат в поле обычной винды, опишу реализацию этих расширений именно для win32.
Итак, исходя из моих наблюдений, модуль для питон написанный на С - простая Dll стандартного формата windows, которая отвечает определенному контракту. Правда есть один нюанс (возможно это не есть общее правило, но пока я не знаю альтернатив), все собранные модули на С/С++ представляют собой DLL, но с форматом имени файла *.pyd и находятся тут: Python27\DLLs\ пока сообразил, убил кучу времени.
По сути создание такого модуля сводится к следующим шагам:
Итак, исходя из моих наблюдений, модуль для питон написанный на С - простая Dll стандартного формата windows, которая отвечает определенному контракту. Правда есть один нюанс (возможно это не есть общее правило, но пока я не знаю альтернатив), все собранные модули на С/С++ представляют собой DLL, но с форматом имени файла *.pyd и находятся тут: Python27\DLLs\ пока сообразил, убил кучу времени.
По сути создание такого модуля сводится к следующим шагам:
- Пишем на С/С++ тела DLL соблюдая контракт. По сути контракт этот гласит, что dll обязана экспортировать функцию (может быть не одна) initXXX, которая по сути призвана произвести все регистрации.
- Собираем её в DLL
- Копируем её в Python27\DLLs\ с расширением *.pyd
- Используем этот модуль так же, как и написанные на питоне (import mymodule)
Вот мой пример пошагово:
- В отдельной папке (CPath) зоздаем исходник CPath.c следующего вида
#include "C:\Python27\include\Python.h"
static PyObject * CPath_findPath(PyObject *self, PyObject *args)
{
//
return NULL;
}
static PyMethodDef CPathMethods[] = {
{"findPath", CPath_findPath, METH_VARARGS, "An error occured while path calculating"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initCPath(void)
{
(void) Py_InitModule("CPath", CPathMethods);
}
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]);
Py_Initialize();
initCPath();
return 0;
}
- после этого собираем объектный файл
gcc -c CPath.c c:\Python27\libs\python27.lib
Получаем: CPath.o
- Собираем саму библиотеку
Получаем: CPath.pyd
- Копируем CPath.pyd в Python27\DLLs\
- Теперь имеем доступный из питона модуль CPath с единственным экспортом findPath()
import CPath
CPath.findPath("Params should be sent here")
- Импорт win32 функций из DLL для windows (удобный подход, можно вызывать как и стандартные API функции так и собственные)
-текст-
- Взаимодействие со стандартными (или) самописными COM объектами
-текст-
Ресурсы, которыми я пользовался для получения знаний:
Lessons in Python/C++ Interactions
Extending Python with C or C++
Python/C API Reference Manual
Где пример использования com объекта? Хоть бы привел пример интеракшина с MS EXCEL
ОтветитьУдалитьДа и про DLL не забывай
ОтветитьУдалить