Литмир - Электронная Библиотека
A
A

// Строка документации метода update

PyDoc_STRVAR(update_doc,

«update (arg)\n\

\n\

Update the md5 object with the string arg. Repeated calls are\n\

equivalent to a single call with the concatenation of all the\n\

arguments.»);

// Метод digest

static PyObject *

md5_digest(md5object *self)

{

MD5_CTX mdContext;

unsigned char aDigest[16];

/* make a temporary copy, and perform the final */

mdContext = self->md5;

MD5Final(aDigest, &mdContext);

// результат возвращается в виде строки

return PyString_FromStringAndSize((char *)aDigest, 16);

}

// и строка документации

PyDoc_STRVAR(digest_doc, «digest() -> string\n\ …»);

static PyObject *

md5_hexdigest(md5object *self)

{

// Реализация метода на C

}

PyDoc_STRVAR(hexdigest_doc, «hexdigest() -> string\n…»);

// Здесь было определение метода copy()

// Методы объекта в сборе.

// Для каждого метода указывается название, имя метода на C

// (с приведением к типу PyCFunction), способ передачи аргументов:

// METH_VARARGS (переменное кол–во) или METH_NOARGS (нет аргументов)

// В конце массива — метка окончания спиcка аргументов.

static PyMethodDef md5_methods[] = {

{«update», (PyCFunction)md5_update, METH_VARARGS, update_doc},

{«digest», (PyCFunction)md5_digest, METH_NOARGS, digest_doc},

{«hexdigest», (PyCFunction)md5_hexdigest, METH_NOARGS, hexdigest_doc},

{«copy», (PyCFunction)md5_copy, METH_NOARGS, copy_doc},

{NULL, NULL} /* sentinel */

};

// Атрибуты md5–объекта обслуживает эта функция, реализуя метод

// getattr.

static PyObject *

md5_getattr(md5object *self, char *name)

{

// атрибут–данное digest_size

if (strcmp(name, «digest_size») == 0) {

return PyInt_FromLong(16);

}

// поиск атрибута–метода ведется в списке

return Py_FindMethod(md5_methods, (PyObject *)self, name);

}

// Строка документации к модулю md5

PyDoc_STRVAR(module_doc, «This module implements …»);

// Строка документации к классу md5

PyDoc_STRVAR(md5type_doc, «An md5 represents the object…»);

// Структура для объекта MD5type с описаниями для интерпретатора

static PyTypeObject MD5type = {

PyObject_HEAD_INIT(NULL)

0, /*ob_size*/

«md5.md5», /*tp_name*/

sizeof(md5object), /*tp_size*/

0, /*tp_itemsize*/

/* methods */

(destructor)md5_dealloc, /*tp_dealloc*/

0, /*tp_print*/

(getattrfunc)md5_getattr, /*tp_getattr*/

0, /*tp_setattr*/

0, /*tp_compare*/

0, /*tp_repr*/

0, /*tp_as_number*/

0, /*tp_as_sequence*/

0, /*tp_as_mapping*/

0, /*tp_hash*/

0, /*tp_call*/

0, /*tp_str*/

0, /*tp_getattro*/

0, /*tp_setattro*/

0, /*tp_as_buffer*/

0, /*tp_xxx4*/

md5type_doc, /*tp_doc*/

};

// Функции модуля md5:

// Функция new() для получения нового объекта типа md5type

static PyObject *

MD5_new(PyObject *self, PyObject *args)

{

md5object *md5p;

unsigned char *cp = NULL;

int len = 0;

// Разбор параметров. Здесь вертикальная черта

// в строке формата означает окончание

// списка обязательных параметров.

// Остальное — как и выше: s# - строка, после : — имя

if (!PyArg_ParseTuple(args, "|s#:new», &cp, &len))

return NULL;

if ((md5p = newmd5object()) == NULL)

return NULL;

// Если был задан параметр cp:

if (cp)

MD5Update(&md5p->md5, cp, len);

return (PyObject *)md5p;

}

// Строка документации для new()

PyDoc_STRVAR(new_doc, «new([arg]) -> md5 object …»);

// Список функций, которые данный модуль экспортирует

static PyMethodDef md5_functions[] = {

{«new», (PyCFunction)MD5_new, METH_VARARGS, new_doc},

{«md5», (PyCFunction)MD5_new, METH_VARARGS, new_doc},

{NULL, NULL} /* Sentinel */

};

// Следует заметить, что md5 — то же самое, что new. Эта функция оставлена для

// обратной совместимости со старым модулем md5

// Инициализация модуля

PyMODINIT_FUNC

initmd5(void)

{

PyObject *m, *d;

MD5type.ob_type = &PyType_Type;

// Инициализируется модуль

m = Py_InitModule3(«md5», md5_functions, module_doc);

// Получается словарь с именами модуля

d = PyModule_GetDict(m);

// Добавляется атрибут MD5Type (тип md5–объекта) к словарю

PyDict_SetItemString(d, «MD5Type», (PyObject *)&MD5type);

// Добавляется целая константа digest_size к модулю

PyModule_AddIntConstant(m, «digest_size», 16);

}

На основе этого примера можно строить собственные модули расширения, ознакомившись с документацией по C/API и документом «Extending and Embedding» («Расширение и встраивание») из стандартной поставки Python. Перед тем, как приступать к созданию своего модуля, следует убедиться, что это целесообразно: подходящего модуля еще не создано и реализация в виде чистого Python неэффективна. Если создан действительно полезный модуль, его можно предложить для включения в поставку Python. Для этого нужно просто связаться с кем–нибудь из разработчиков по электронной почте или предложить модуль в виде «патча» через http://sourceforge.net.

Пример встраивания интерпретатора в программу на C

Интерпретатор 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 time\n»);

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 порождает код, не зависящий от позиции, что позволяет в дальнейшем динамически компоновать код

55
{"b":"429288","o":1}