I have been getting my feet wet with writing Python modules in C. I've started with just a simple example of computing the norm of two points. The code looks like this,
_norm.c
#include <Python.h>
#include "norm.h"
static char module_docstring[] =
"This module provides an interface for computing the norm using C.";
static char norm_docstring[] =
"Calculate the norm between two points";
static char norm2_docstring[] =
"Calculate the square norm between two points. For efficiency.";
static PyObject *norm_norm(PyObject *self, PyObject *args);
static PyObject *norm_norm2(PyObject *self, PyObject *args);
static PyMethodDef module_methods[] = {
{"norm", norm_norm, METH_VARARGS, norm_docstring},
{"norm2", norm_norm2, METH_VARARGS, norm2_docstring},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC init_norm(void) {
PyObject *m = Py_InitModule3("_norm", module_methods, module_docstring);
if (m == NULL)
return;
}
static PyObject *norm_norm(PyObject *self, PyObject *args) {
double x1, y1, x2, y2;
/* Parse the input tuple */
if (!PyArg_ParseTuple(args, "ddOOO", &x1, &y1, &x2, &y2))
return NULL;
/* Call the external C function to compute the norm. */
double value = norm(x1, y1, x2, y2);
if (value < 0.0) {
PyErr_SetString(PyExc_RuntimeError,
"Norm returned an impossible value.");
}
PyObject *ret = Py_BuildValue("d", value);
return ret;
}
norm.c
#include <math.h>
long double norm2(long double x1, long double y1, long double x2, long double y2) {
long double xd = x2 - x1;
long double yd = y2 - y1;
return xd * xd + yd * yd;
}
long double norm(long double x1, long double y1, long double x2, long double y2) {
return sqrt(norm2(x1, y1, x2, y2));
}
setup.py
from distutils.core import setup, Extension
setup(
ext_modules=[Extension("_norm", ["_norm.c", "norm.c"])]
)
I build the package like this,
python setup.py build_ext --inplace
And it compiles with no problems. However, when I try to use it I get an error about the number of arguments.
>>> import _norm
>>> _norm.norm(1,2,5,6)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function takes exactly 5 arguments (4 given)
I guess it might have something to do with the declaration of PyObject *norm_norm() because it gets passed *self, but I'm not sure if that should effect the arguments that I pass to the module on the Python side of things. I'd appreciate any help/suggestions.