|
|
|
|
Extending Python Example with C
|
|
|
|
$ cat e.c
int fonk (int n)
{
return n + 1;
}
$ cat w.c
#include <Python.h>
PyObject * wrap_fonk (PyObject *self, PyObject *args)
{
int n;
int result;
if (!PyArg_ParseTuple(args, "i:fonk", &n)) {
return NULL;
}
result = fonk(n);
return Py_BuildValue("i", result);
}
static PyMethodDef exampleMethods[] = {
{"fonk", wrap_fonk, 1},
{NULL, NULL}
};
void initexample (void)
{
PyObject *m;
m = Py_InitModule("example", exampleMethods);
}
$ gcc -fpic -c e.c w.c
$ gcc -shared e.o w.o -o example.dll
/usr/lib/python2.4/config/libpython2.4.dll.a
$ cp example.dll /usr/lib/python2.4/libdyn-load/
$ python
>>> import example
>>> example.fonk(2);
3
>>>
ctrl + d
$ cok $Ik
bash: cok: command not found
|
|
$ cat e.c
typedef struct class_s {
int i;
} class_t;
int st_new (class_t **st)
{
*st = (class_t *) malloc(sizeof(class_t));
(*st)->i = 0;
return 0;
}
int st_del (class_t *st)
{
free(st);
return 0;
}
int st_set_i (class_t *st, int i)
{
st->i = i;
return 0;
}
int st_get_i (class_t *st, int *i)
{
*i = st->i;
return 0;
}
$ cat w.c
#include <Python.h>
#include <structmember.h>
typedef struct class_s {
int i;
} class_t;
int st_new (class_t **st);
int st_del (class_t *st);
int st_set_i (class_t *st, int i);
int st_get_i (class_t *st, int *i);
static PyObject * St (PyObject *self, PyObject *args);
typedef struct _class_s {
PyObject_HEAD
class_t *st;
} _class_t;
static int pyobject_to_int (PyObject* obj, int* val)
{
PyObject *intobj;
if (PyNumber_Check(obj)) {
if (!(intobj = PyNumber_Int(obj))) {
PyErr_Clear();
return 0;
}
*val = PyInt_AsLong(intobj);
Py_DECREF(intobj);
if (PyErr_Occurred()) {
PyErr_Clear();
return 0;
}
return 1;
}
return 0;
}
static void _class_dealloc (PyObject *obj)
{
_class_t *self = (_class_t *) obj;
st_del(self->st);
obj->ob_type->tp_free(obj);
}
static PyObject * _class_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
return St(NULL, args);
}
static int _class_init (_class_t *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"i", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &self->st->i))
return -1;
return 0;
}
static PyObject * _class_get_i (_class_t *self, void *closure)
{
int i;
st_get_i(self->st, &i);
return Py_BuildValue("i", i);
}
static int _class_set_i (_class_t *self, PyObject *value, void *closure)
{
int i;
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "value == null");
return -1;
}
if (!PyInt_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value != integer");
return -1;
}
pyobject_to_int(value, &i);
return st_set_i(self->st, i);
}
static PyObject * get_i (PyObject *self, PyObject *args)
{
return _class_get_i((_class_t *) self, NULL);
}
static PyObject * set_i (PyObject *self, PyObject *args)
{
int i;
if (!PyArg_ParseTuple(args, "i", &i))
return NULL;
return Py_BuildValue("i", _class_set_i((_class_t *) self, Py_BuildValue("i", i), NULL));
}
static PyMethodDef _class_methods[] = {
{"get_i", get_i, 1},
{"set_i", set_i, 1},
{NULL, NULL}
};
static PyGetSetDef _class_getseters[] = {
{"i", (getter) _class_get_i, (setter) _class_set_i, "_class i", NULL},
{NULL}
};
static PyTypeObject _class_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"_class", /* tp_name */
sizeof(_class_t), /* tp_basicsize */
0, /* tp_itemsize */
_class_dealloc, /* 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_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags*/
"_class object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
_class_methods, /* tp_methods */
0, /* tp_members */
_class_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) _class_init, /* tp_init */
0, /* tp_alloc */
_class_new, /* tp_new */
};
static PyObject * St (PyObject *self, PyObject *args)
{
int res;
_class_t *st = PyObject_New(_class_t, &_class_type);
res = st_new(&(st->st));
if (res) {
PyErr_SetString(PyExc_TypeError, "st_new failed");
return NULL;
}
return (PyObject *) st;
}
static PyMethodDef example_methods[] = {
{"St", St, 1},
{NULL, NULL}
};
void initexample (void)
{
PyObject *m;
PyObject *dict;
if (PyType_Ready(&_class_type) < 0)
return;
_class_type.ob_type = &PyType_Type;
m = Py_InitModule3("example", example_methods, "Example module.");
Py_INCREF(&_class_type);
PyModule_AddObject(m, "_class", (PyObject *) &_class_type);
}
$ cat Makefile
all:
gcc -fpic -c -I/usr/include/python2.4 e.c w.c
gcc -shared e.o w.o -o example.dll /usr/lib/python2.4/config/libpython2.4.dll.a
cp example.dll /usr/lib/python2.4/lib-dynload/
$ make
gcc -fpic -c -I/usr/include/python2.4 e.c w.c
e.c:1: warning: -fpic ignored for target (all code is position independent)
w.c:1: warning: -fpic ignored for target (all code is position independent)
gcc -shared e.o w.o -o example.dll /usr/lib/python2.4/config/libpython2.4.dll.a
cp example.dll /usr/lib/python2.4/lib-dynload/
$ python
Python 2.4.1 (#1, May 27 2005, 18:02:40)
[GCC 3.3.3 (cygwin special)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> s = example.St()
>>> s.i
0
>>> s.i = 9
>>> s.i
9
>>> s.set_i(10);
0
>>> s.i
10
>>> s.get_i();
10
>>> cok $ik ;)
File "<stdin>", line 1
cok $ik ;)
^
SyntaxError: invalid syntax
>>> del s
|
|
|
|
|
|
|