`
Читать книги » Книги » Компьютеры и Интернет » Программирование » Роман Сузи - Язык программирования Python

Роман Сузи - Язык программирования Python

1 ... 51 52 53 54 55 ... 59 ВПЕРЕД
Перейти на страницу:

Интерпретатор Python может быть встроен в программу на C с использованием C API. Это лучше всего демонстрирует уже работающий пример:

/* File : demo.c */

/* Пример встраивания интерпретатора Python в другую программу */

#include "Python.h"

main(int argc, char **argv) {

 /* Передает argv[0] интерпретатору Python */

 Py_SetProgramName(argv[0]);

 /* Инициализация интерпретатора */

 Py_Initialize();

 /* ... */

 /* Выполнение операторов Python (как бы модуль __main__) */

 PyRun_SimpleString("import timen");

 PyRun_SimpleString("print time.localtime(time.time())n");

 /* ... */

 /* Завершение работы интерпретатора */

 Py_Finalize();

}

Компиляция этого примера с помощью компилятора gcc может быть выполнена, например, так:

ver="2.3"

gcc–fpic demo.c–DHAVE_CONFIG_H–lm–lpython${ver}

 -lpthread–lutil–ldl

 -I/usr/local/include/python${ver}

 -L/usr/local/lib/python${ver}/config

 -Wl, -E

 -o demo

Здесь следует отметить следующие моменты:

• программу необходимо компилировать вместе с библиотекой libpython соответствующей версии (для этого используется опция –l, за которой следует имя библиотеки) и еще с библиотеками, которые требуются для Python: libpthread, libm, libutil и т.п.)

• опция pic порождает код, не зависящий от позиции, что позволяет в дальнейшем динамически компоновать код

• обычно требуется явно указать каталог, в котором лежит заголовочный файл Python.h (в gcc это делается опцией –I)

• чтобы получившийся исполняемый файл мог корректно предоставлять имена для динамически загружаемых модулей, требуется передать компоновщику опцию –E: это можно сделать из gcc с помощью опции –Wl, -E. (В противном случае, модуль time, а это модуль расширения в виде динамически загружаемого модуля, не будет работать из–за того, что не увидит имен, определенных в libpython)

Здесь же следует сделать еще одно замечание: программа, встраивающая Python, не должна много раз выполнять Py_Initialize() и Py_Finalize(), так как это может приводить к утечке памяти. Сам же интерпретатор Python очень стабилен и в большинстве случаев не дает утечек памяти.

Использование SWIG

SWIG (Simplified Wrapper and Interface Generator, упрощенный упаковщик и генератор интерфейсов) — это программное средства, сильно упрощающее (во многих случаях — автоматизирующее) использование библиотек, написанных на C и C++, а также на других языках программирования, в том числе (не в последнюю очередь!) на Python. Нужно отметить, что SWIG обеспечивает достаточно полную поддержку практически всех возможностей C++, включая предобработку, классы, указатели, наследование и даже шаблоны C++. Последнее очень важно, если необходимо создать интерфейс к библиотеке шаблонов.

Пользоваться SWIG достаточно просто, если уметь применять компилятор и компоновщик (что в любом случае требуется при программировании на C/C++).

Простой пример использования SWIG

Предположим, что есть программа на C, реализующая некоторую функцию (пусть это будет вычисление частоты появления различных символов в строке):

/* File : freq.c */

#include <stdlib.h>

int * frequency(char s[]) {

 int *freq;

 char *ptr;

 freq = (int*)(calloc(256, sizeof(int)));

 if (freq != NULL)

  for (ptr = s; *ptr; ptr++)

   freq[*ptr] += 1;

 return freq;

}

Для того чтобы можно было воспользоваться этой функцией из Python, нужно написать интерфейсный файл (расширение .i) примерно следующего содержания:

/* File : freq.i */

%module freq

%typemap(out) int * {

 int i;

 $result = PyTuple_New(256);

 for(i=0; i<256; i++)

  PyTuple_SetItem($result, i, PyLong_FromLong($1[i]));

 free($1);

}

extern int * frequency(char s[]);

Интерфейсные файлы содержат инструкции самого SWIG и фрагменты C/C++-кода, возможно, с макровключениями (в примере выше: $result, $1). Следует заметить, что для преобразования массива целых чисел в кортеж элементов типа long, необходимо освободить память из–под исходного массива, в котором подсчитывались частоты.

Теперь (подразумевая, что используется компилятор gcc), создание модуля расширения может быть выполнено примерно так:

swig–python freq.i

gcc–c–fpic freq_wrap.c freq.c -DHAVE_CONFIG_H

-I/usr/local/include/python2.3

–I/usr/local/lib/python2.3/config

gcc–shared freq.o freq_wrap.o–o _freq.so

После этого в рабочем каталоге появляется файлы _freq.so и freq.py, которые вместе и дают доступ к требуемой функции:

>>> import freq

>>> freq.frequency("ABCDEF")[60:75]

(0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L)

Помимо этого, можно посмотреть на содержимое файла freq_wrap.c, который был порожден SWIG: в нем, среди прочих вспомогательных определений, нужных самому SWIG, можно увидеть что–то подобное проиллюстрированному выше примеру модуля md5. Вот фрагмент этого файла с определением обертки для функции frequency():

extern int *frequency(char []);

static PyObject *_wrap_frequency(PyObject *self, PyObject *args) {

 PyObject *resultobj;

 char *arg1;

 int *result;

 if(!PyArg_ParseTuple(args,(char *)"s:frequency",&arg1)) goto fail;

 result = (int *)frequency(arg1);

 {

  int i;

  resultobj = PyTuple_New(256);

  for(i=0; i<256; i++)

   PyTuple_SetItem(resultobj, i, PyLong_FromLong(result[i]));

  free(result);

 }

 return resultobj;

fail:

 return NULL;

}

В качестве упражнения, предлагается сопоставить это определение с файлом freq.i и понять, что происходит внутри функции _wrap_frequency(). Подсказка: можно посмотреть еще раз комментарии к C–коду модуля md5.

Стоит еще раз напомнить, что в отличие от Python, в языке C/C++ управление памятью должно происходить в явном виде. Именно поэтому добавлена функция free() при преобразовании типа. Если этого не сделать, возникнут утечки памяти. Эти утечки можно обнаружить, при многократном выполнении функции:

>>> import freq

>>> for i in xrange(1000000):

... dummy = freq.frequency("ABCDEF")

>>>

Если функция freq.frequency() имеет утечки памяти, выполняемый процесс очень быстро займет всю имеющуюся память.

Интеграция Python и других систем программирования

Язык программирования Python является сценарным языком, а значит его основное назначение — интеграция в единую систему разнородных программных компонентов. Выше рассматривалась (низкоуровневая) интеграция с C/C++-приложениями. Нужно заметить, что в большинстве случаев достаточно интеграции с использованием протокола. Например, интегрируемые приложения могут общаться через XML–RPC, SOAP, CORBA, COM, .NET и т.п. В случаях, когда приложения имеют интерфейс командной строки, их можно вызывать из Python и управлять стандартным вводом–выводом, переменными окружения. Однако есть и более интересные варианты интеграции.

Современное состояние дел по излагаемому вопросу можно узнать по адресу: http://www.python.org/moin/IntegratingPythonWithOtherLanguages

Java

Документация по Jython (это реализация Python на Java–платформе) отмечает, что Jython обладает следующими неоспоримыми преимуществами над другими языками, использующими Java–байт-код:

• Jython–код динамически компилирует байт-коды Java, хотя возможна и статическая компиляция, что позволяет писать апплеты, сервлеты и т.п.;

• Поддерживает объектно–ориентированную модель Java, в том числе, возможность наследовать от абстрактных Java–классов;

• Jython является реализацией Python — языка с практичным синтаксисом, обладающего большой выразительностью, что позволяет сократить сроки разработки приложений в разы.

Правда, имеются и некоторые ограничения по сравнению с «обычным» Python. Например, Java не поддерживает множественного наследования, поэтому в некоторых версиях Jython нельзя наследовать классы от нескольких Java–классов (в тоже время, множественное наследование поддерживается для Python–классов).

Следующий пример (файл lines.py) показывает полную интеграцию Java–классов с интерпретатором Python:

# Импортируются модули из Java

from java.lang import System

from java.awt import *

# А это модуль из Jython

import random

# Класс для рисования линий на рисунке

class Lines(Canvas):

 # Реализация метода paint()

 def paint(self, g):

  X, Y = self.getSize().width, self.getSize().height

  label.setText("%s x %s" % (X, Y))

1 ... 51 52 53 54 55 ... 59 ВПЕРЕД
Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Роман Сузи - Язык программирования Python, относящееся к жанру Программирование. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)