Created
September 14, 2012 11:09
-
-
Save amintos/3721336 to your computer and use it in GitHub Desktop.
Example interfacing plain arrays via NumPy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Python.h" | |
#include "numpy/arrayobject.h" | |
// ---------------------------------------------------------------------------- | |
// BASIC API | |
typedef struct { | |
int data[1024]; | |
} internalColumn; | |
void setEntry(internalColumn *col, int index, int value) | |
{ | |
//printf("%i, %i\n", index, value); | |
(col->data)[index] = value; | |
} | |
int getEntry(internalColumn *col, int index) | |
{ | |
//printf("%i\n", index); | |
return (col->data)[index]; | |
} | |
// ---------------------------------------------------------------------------- | |
// WRAPPER TYPE | |
typedef struct { | |
PyObject_HEAD | |
internalColumn data; | |
} foo_ColumnObject; | |
// ---------------------------------------------------------------------------- | |
// MAPPING INTERFACE | |
PyObject * PyColumn_GetItem(foo_ColumnObject *self, PyObject *key); | |
int PyColumn_SetItem(foo_ColumnObject *self, PyObject *key, PyObject *value); | |
Py_ssize_t PyColumn_Length(foo_ColumnObject* self); | |
// ---------------------------------------------------------------------------- | |
// ITERATOR INTERFACE | |
PyObject * PyColumn_iter(PyObject *self, PyObject *args); | |
PyObject * ColumnIterator_iter(PyObject *self); | |
PyObject * ColumnIterator_next(PyObject *self); | |
// ---------------------------------------------------------------------------- | |
// ITERATOR TYPE | |
typedef struct { | |
PyObject_HEAD | |
foo_ColumnObject *column; | |
Py_ssize_t iter_count; | |
Py_ssize_t iter_index; | |
} foo_ColumnIterator; | |
// ---------------------------------------------------------------------------- | |
// ITERATOR IMPLEMENTATION | |
// __iter__ of an iterator should return a new reference on self | |
PyObject* ColumnIterator_iter(PyObject *self) | |
{ | |
Py_INCREF(self); | |
return self; | |
} | |
PyObject* ColumnIterator_next(PyObject *self) | |
{ | |
foo_ColumnIterator *t_self = (foo_ColumnIterator *)self; | |
if (t_self->iter_index < t_self->iter_count) | |
{ | |
return PyInt_FromSsize_t(t_self->column->data.data[t_self->iter_index++]); | |
} | |
else | |
{ | |
PyErr_SetNone(PyExc_StopIteration); | |
return NULL; | |
} | |
} | |
static PyTypeObject foo_ColumnIteratorType = { | |
PyObject_HEAD_INIT(NULL) | |
0, /*ob_size*/ | |
"foo.ColumnIterator", /*tp_name*/ | |
sizeof(foo_ColumnIterator), /*tp_basicsize*/ | |
0, /*tp_itemsize*/ | |
0, /*tp_dealloc*/ | |
0, /*tp_print*/ | |
0, /*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*/ | |
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, | |
/* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to | |
use tp_iter and tp_iternext fields. */ | |
"Column Iterator", /* tp_doc */ | |
0, /* tp_traverse */ | |
0, /* tp_clear */ | |
0, /* tp_richcompare */ | |
0, /* tp_weaklistoffset */ | |
ColumnIterator_iter, /* tp_iter: __iter__() method */ | |
ColumnIterator_next /* tp_iternext: next() method */ | |
}; | |
PyObject * PyColumn_iter(PyObject *self, PyObject *args) | |
{ | |
foo_ColumnIterator* iter = PyObject_New( | |
foo_ColumnIterator, | |
&foo_ColumnIteratorType); | |
iter->iter_count = 1024; | |
iter->iter_index = 0; | |
iter->column = (foo_ColumnObject*)(self); | |
return iter; | |
} | |
// ---------------------------------------------------------------------------- | |
// ADAPTER TYPE | |
// --- Mapping Interface --- // | |
static PyMappingMethods foo_ColumnType_mapping = { | |
(lenfunc)PyColumn_Length, // lenfunc PyMappingMethods.mp_length | |
(binaryfunc)PyColumn_GetItem, // binaryfunc PyMappingMethods.mp_subscript | |
(objobjargproc)PyColumn_SetItem, // objobjargproc PyMappingMethods.mp_ass_subscript | |
}; | |
// -!- Mapping Interface -!- // | |
// --- Array Interface --- // | |
PyObject * PyColumn_Array(foo_ColumnObject *self, PyObject *args); | |
// -!- Array Interface -!- // | |
// --- VMT --- // | |
static struct PyMethodDef foo_ColumnType_methods[] = { | |
{"array", &PyColumn_Array, METH_VARARGS, "As Numpy-Array"}, | |
{NULL, NULL, NULL, NULL} | |
}; | |
// -!- VMT -!- // | |
static PyTypeObject foo_ColumnType = { | |
PyObject_HEAD_INIT(NULL) | |
0, /*ob_size*/ | |
"foomodule.Column", /*tp_name*/ | |
sizeof(foo_ColumnObject), /*tp_basicsize*/ | |
0, /*tp_itemsize*/ | |
0, /*tp_dealloc*/ | |
0, /*tp_print*/ | |
0, /*tp_getattr*/ | |
0, /*tp_setattr*/ | |
0, /*tp_compare*/ | |
0, /*tp_repr*/ | |
0, /*tp_as_number*/ | |
0, /*tp_as_sequence*/ | |
&foo_ColumnType_mapping, /*tp_as_mapping*/ | |
0, /*tp_hash */ | |
0, /*tp_call*/ | |
0, /*tp_str*/ | |
0, /*tp_getattro*/ | |
0, /*tp_setattro*/ | |
0, /*tp_as_buffer*/ | |
Py_TPFLAGS_DEFAULT, /*tp_flags*/ | |
"Sample Columns", /* tp_doc */ | |
0, //traversrceproc tp_traverse; | |
/* delete references to contained objects */ | |
0, //inquiry tp_clear; | |
/* Assigned meaning in release 2.1 */ | |
/* rich comparisons */ | |
0, //richcmpfunc tp_richcompare; | |
/* weak reference enabler */ | |
0, //long tp_weaklistoffset; | |
/* Added in release 2.2 */ | |
/* Iterators */ | |
&PyColumn_iter, //getiterfunc tp_iter; | |
0, //iternextfunc tp_iternext; | |
/* Attribute descriptor and subclassing stuff */ | |
foo_ColumnType_methods, //struct PyMethodDef *tp_methods; | |
0, //struct PyMemberDef *tp_members; | |
0, //struct PyGetSetDef *tp_getset; | |
0, //struct _typeobject *tp_base; | |
0, //PyObject *tp_dict; | |
0, //descrgetfunc tp_descr_get; | |
0, //descrsetfunc tp_descr_set; | |
0, //long tp_dictoffset; | |
0, //initproc tp_init; | |
0, //allocfunc tp_alloc; | |
0, //newfunc tp_new; | |
0, //freefunc tp_free; /* Low-level free-memory routine */ | |
0, //inquiry tp_is_gc; /* For PyObject_IS_GC */ | |
0, //PyObject *tp_bases; | |
0, //PyObject *tp_mro; /* method resolution order */ | |
0, //PyObject *tp_cache; | |
0, //PyObject *tp_subclasses; | |
0, //PyObject *tp_weaklist; | |
}; | |
// ---------------------------------------------------------------------------- | |
// IMPLEMENTATION | |
PyObject * PyColumn_GetItem(foo_ColumnObject *self, PyObject *key) | |
{ | |
int intkey = (int)(((PyIntObject*)key)->ob_ival); | |
PyObject *result = PyInt_FromLong((long)getEntry(&(self->data), intkey)); | |
Py_INCREF(result); | |
return result; | |
} | |
int PyColumn_SetItem(foo_ColumnObject *self, PyObject *key, PyObject *value) | |
{ | |
int intkey = (int)(((PyIntObject*)key)->ob_ival); | |
int intvalue = (int)(((PyIntObject*)value)->ob_ival); | |
setEntry(&(self->data), intkey, intvalue); | |
return 0; | |
} | |
Py_ssize_t PyColumn_Length(foo_ColumnObject* self) { | |
return 1024; | |
} | |
PyObject * PyColumn_Array(foo_ColumnObject *self, PyObject *args) { | |
npy_intp dims = {1024}; | |
Py_INCREF(self); | |
PyObject* array = PyArray_SimpleNewFromData(1, &dims, NPY_INT32, self->data.data); | |
//PyObject *array = Py_None; | |
Py_INCREF(array); | |
return array; | |
} | |
// ---------------------------------------------------------------------------- | |
// MOODULE IINITIALIZATION | |
static PyObject * | |
ex_foo(PyObject *self, PyObject *args) | |
{ | |
printf("Hello, world\n"); | |
Py_INCREF(Py_None); | |
return Py_None; | |
} | |
static PyMethodDef example_methods[] = { | |
{"foo", ex_foo, METH_VARARGS, "foo() doc string"}, | |
{NULL, NULL} | |
}; | |
PyMODINIT_FUNC | |
initfoomodule(void) | |
{ | |
PyObject* this_module; | |
foo_ColumnType.tp_new = PyType_GenericNew; | |
if (PyType_Ready(&foo_ColumnType) < 0) | |
return; | |
if (PyType_Ready(&foo_ColumnIteratorType) < 0) | |
return; | |
this_module = Py_InitModule("foomodule", example_methods); | |
PyModule_AddObject(this_module, "Column", (PyObject *)&foo_ColumnType); | |
Py_INCREF(&foo_ColumnType); | |
Py_INCREF(&foo_ColumnIteratorType); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment