Help creating extension for C function

Fredrik Lundh fredrik at pythonware.com
Sat Oct 8 10:22:06 EDT 2005


"Java and Swing" wrote:

>I need to write an extension for a C function so that I can call it
> from python.
>
> C code (myapp.c)
> ======
> typedef unsigned long MY_LONG;
>
> char *DoStuff(char *input, MY_LONG *x) { ... }
>
> so you pass in a string and an array of MY_LONGS...such as
>
> MY_LONGS vals[10] = {....};
> char *input = "this is my input";
> char *result;
>
> result = DoStuff(input, vals);
>
> ...I need to create an extension so that I can call this from Python
> such as...
>
>>> import myapp
>>> vals = [1,2,3,4,5,6,7,8,9,10]
>>> input = "this is my input"
>>> result = myapp.DoStuff(input, vals)
>>> print result
>
> ideally the result would be a String, vals would be a list and input
> would be a string.

$ more module.c

/* $Id$ */
/* a module */

#include "Python.h"

static long*
get_long_array(PyObject* data, int* data_size)
{
    int i, size;
    long* out;
    PyObject* seq;

    seq = PySequence_Fast(data, "expected a sequence");
    if (!seq)
        return NULL;

    size = PySequence_Size(seq);
    if (size < 0)
        return NULL;

    if (data_size)
        *data_size = size;

    out = (long*) PyMem_Malloc(size * sizeof(long));
    if (!out) {
        Py_DECREF(seq);
        PyErr_NoMemory();
        return NULL;
    }

    for (i = 0; i < size; i++)
        out[i] = PyInt_AsLong(PySequence_Fast_GET_ITEM(seq, i));

    Py_DECREF(seq);

    if (PyErr_Occurred()) {
        PyMem_Free(out);
        out = NULL;
    }

    return out;
}

static PyObject*
do_stuff(PyObject* self, PyObject* args)
{
    int i;
    long* vals;
    int vals_size;

    char* my_result;

    char* input;
    PyObject* vals_in;
    if (!PyArg_ParseTuple(args, "sO:do_stuff", &input, &vals_in))
        return NULL;

    vals = get_long_array(vals_in, &vals_size);
    if (!vals)
        return NULL;

    if (vals_size != 10) {
        PyErr_SetString(PyExc_ValueError, "expected 10 values");
        PyMem_Free(vals);
        return NULL;
    }

    /* do stuff */
    printf("input = %s\n", input);
    for (i = 0; i < 10; i++)
        printf("vals[%d] = %ld\n", i, vals[i]);
    my_result = "result";
    /* done */

    PyMem_Free(vals);

    return PyString_FromString(my_result);
}

static PyMethodDef functions[] = {
    {"do_stuff", do_stuff, METH_VARARGS},
    {NULL, NULL}
};

PyMODINIT_FUNC initmodule(void)
{
    Py_InitModule4(
        "module", functions, "my module", NULL, PYTHON_API_VERSION
        );
}

$ more setup.py

# $Id$
# a setup file

from distutils.core import setup, Extension

setup(
    name="module",
    ext_modules = [Extension("module", ["module.c"])]
    )

$ python setup.py build_ext -i
...

$ python
>>> import module
>>> vals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> input = "this is some input"
>>> result = module.do_stuff(input, vals)
input = this is some input
vals[0] = 1
vals[1] = 2
vals[2] = 3
vals[3] = 4
vals[4] = 5
vals[5] = 6
vals[6] = 7
vals[7] = 8
vals[8] = 9
vals[9] = 10
>>> result
'result'

</F> 






More information about the Python-list mailing list