Язык программирования Python
Шрифт:
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,
// Здесь было определение метода 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]);
/* Инициализация интерпретатора */