Язык программирования Python
Шрифт:
Листинг
// заголовочные файлы
#include «Python.h»
#include «md5.h»
// В частности, в заголовочном файле md5.h есть следующие определения:
// typedef unsigned char *POINTER;
// typedef unsigned int UINT4;
// typedef struct {
// UINT4 state[4]; /* state (ABCD) */
// UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
// unsigned char buffer[64]; /* input buffer */
// } MD5_CTX;
//
typedef struct {
PyObject_HEAD
MD5_CTX md5; /* the context holder */
} md5object;
// Определение типа объекта MD5type
static PyTypeObject MD5type;
// Макрос проверки типа MD5type
#define is_md5object(v) ((v) — >ob_type == &MD5type)
// Порождение объекта типа MD5type
static md5object *
newmd5object(void)
{
md5object *md5p;
md5p = PyObject_New(md5object, &MD5type);
if (md5p == NULL)
return NULL; // не хватило памяти
MD5Init(&md5p->md5); // инициализация
return md5p;
}
// Определения методов
// Освобождение памяти из–под объекта
static void
md5_dealloc(md5object *md5p) { PyObject_Del(md5p); }
static PyObject *
md5_update(md5object *self, PyObject *args)
{
unsigned char *cp;
int len;
// разбор строки аргументов. Формат указывает следующее:
// s# - один параметр, строка (заданная указателем и длиной)
// : — разделитель
// update — название метода
if (!PyArg_ParseTuple(args, «s#:update», &cp, &len))
return NULL;
MD5Update(&self->md5, cp, len);
// Даже возврат None требует увеличения счетчика ссылок
Py_INCREF(Py_None);
return Py_None;
}
// Строка документации метода 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*/