Но достаточно о C++: вернемся к Python. Чтобы использовать класс C++ Number из предыдущего раздела в сценариях Python, нужно написать или сгенерировать слой связующей логики между двумя языками, как в предыдущих примерах расширений на C. Чтобы автоматически сгенерировать этот слой, напишем входной файл SWIG, как показано в примере 20.17.
Пример 20.17. PP4E\Integrate\Extend\Swig\Shadow\number.i /**************************************************************** * Файл Swig с описанием модуля для обертывания класса C++.
* Генерация выполняется командой "swig —c++ —python number.i".
* Сгенерированный модуль C++ сохраняется в файле number_wrap.cxx;
* модуль ‘number‘ ссылается на теневой класс в модуле number.py.
****************************************************************/ %module number
%{
#include "number.h"
%}
%include number.h
Этот интерфейс просто указывает SWIG, что он должен прочесть данные с сигнатурой типа класса C++ из включаемого заголовочного файла number.h. SWIG снова создает по объявлению класса два разных модуля Python:
number_wrap.cxx
Модуль расширения C++ с функциями доступа к классу.
number.py
Модуль с теневым классом Python, служащим оберткой для функций доступа.
Первый из них должен быть скомпилирован в двоичный файл библиотеки. Второй предназначен для импортирования и использования скомпилированного представления первого файла, и в конечном итоге он сам должен импортироваться в сценариях Python. Как и в примерах с простыми функциями, SWIG решает проблему интеграции за счет комбинирования программного кода на языках Python и C++.
После запуска SWIG make-файл для Cygwin, представленный в примере 20.18, объединит сгенерированный модуль number_wrap.cxx с программным кодом обертки C++ и реализацию класса и создаст файл _number.dll — динамически загружаемый модуль расширения, который к моменту импортирования должен находиться в пути поиска модулей Python, а также файл number.py (все файлы в данном случае находятся в текущем рабочем каталоге).
Как и прежде, при использовании современной версии SWIG имя модуля скомпилированного расширения на C должно начинаться с символа подчеркивания: _number.dll, следуя соглашениям Python, а не в других форматах, использовавшихся в более ранних версиях. Модуль number.py теневого класса импортирует _number.dll. Не забывайте использовать ключ -c++ командной строки SWIG; ранее использовавшийся ключ -shadow более не требуется указывать, чтобы создать обертку для класса в дополнение к низкоуровневому интерфейсу функций модуля, так как он подразумевается по умолчанию.
Пример 20.18. PP4E\Integrate\Extend\Swig\Shadow\makefile.number-swig
########################################################################### # Использование SWIG для интеграции класса C++ number.h с программами Python. # Обновление: имя "_number.dll" имеет важное значение, потому что теневой # класс импортирует модуль _number.
# Обновление: ключ "-shadow" командной строки swig более не требуется
# (подразумевается по умолчанию).
# Обновление: swig более не создает файл .doc и его не нужно удалять здесь
# (это довольно старая история).
###########################################################################
PYLIB = /usr/local/bin
PYINC = /usr/local/include/python3.1
SWIG = /cygdrive/c/temp/swigwin-2.0.0/swig
all: _number.dll number.py
# обертка + действительный класс _number.dll: number_wrap.o number.o g++ -shared number_wrap.o number.o -L$(PYLIB) -lpython3.1 -o $@
# генерирует модуль обертки класса number_wrap.o: number_wrap.cxx number.h g++ number_wrap.cxx -c -g -I$(PYINC)
number_wrap.cxx: number.i
$(SWIG) -c++ -python number.i
number.py: number.i
$(SWIG) -c++ -python number.i
# программный код обертки класса C++ number.o: number.cxx number.h
g++ number.cxx -c -g -Wno-deprecated
# тестовая программа не на Python cxxtest:
g++ main.cxx number.cxx -Wno-deprecated
clean:
rm -f *.pyc *.o *.dll core a.exe force:
rm -f *.pyc *.o *.dll core a.exe number_wrap.cxx number.py
Как обычно, воспользуйтесь этим make-файлом, чтобы сгенерировать и откомпилировать необходимый связующий код в виде модуля расширения, который может импортироваться программами Python:
…/PP4E/Integrate/Extend/Swig/Shadow$ make -f makefile.number-swig /cygdrive/c/temp/swigwin-2.0.0/swig -c++ -python number.i g++ number_wrap.cxx -c -g -I/usr/local/include/python3.1 g++ number.cxx -c -g -Wno-deprecated
g++ -shared number_wrap.o number.o -L/usr/local/bin -lpython3.1 -o _number.dll
…/PP4E/Integrate/Extend/Swig/Shadow$ ls
_number.dll makefile.number-swig number.i number_wrap.cxx a.exe number.cxx number.o number_wrap.o
main.cxx number.h number.py
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, II том, 2011