package pure python and c extension modules
a python project may contain both pure python and c extension modules; now we see how to package them together;
specifically, assume we are writing a package foo
, which provides an adder
function; in fact, two: one implemented in pure python, the other in c as an
extension; we want to make both functions available to our package users; for
example, users can call foo.pyadd()
or foo.cadd()
, at they will;
to make things clean, we put each adder function in its own module; our project dir looks something like this:
.
├── foo
│ ├── clib.c
│ ├── __init__.py
│ └── pylib.py
└── setup.py
function implementations
the function implementations are trivial:
## pylib.py
def pyadd(a, b):
return a + b
// clib.c
#include <Python.h>
static int add(int a, int b)
{
return a + b;
}
static PyObject *
clib_cadd(PyObject *self, PyObject *args)
{
int a, b;
if (!PyArg_ParseTuple(args, "ii", &a, &b))
return NULL;
int c = add(a, b);
return PyLong_FromLong(c);
}
static PyMethodDef ClibMethods[] = {
{ "cadd", clib_cadd, METH_VARARGS, "" },
{ NULL, NULL, 0, NULL }
};
static struct PyModuleDef ClibModule = {
PyModuleDef_HEAD_INIT,
"clib",
"",
-1,
ClibMethods
};
PyMODINIT_FUNC
PyInit_clib(void)
{
return PyModule_Create(&ClibModule);
}
setup script
the setup script setup.py
is also very simple:
from setuptools import Extension
from setuptools import setup
setup(
name='foo',
py_modules=['foo.pylib'],
ext_modules=[Extension('foo.clib',['foo/clib.c'])],
)
here we have two modules:
-
pure python module
foo.pylib
; -
c extension module
foo.clib
;
it is straightforward to list them in py_modules
and ext_modules
,
respectively; feel free to use packages
instead of py_modules
if you want to
list a whole package instead of each of its modules; but packages
only
includes pure python modules (not c extension modules);
test
to test our project, build and install:
python3 build setup.py
python3 install setup.py
then test both adder functions:
# python3 -c "import foo.pylib; print(foo.pylib.pyadd(3, 4))"
7
# python3 -c "import foo.clib; print(foo.clib.cadd(3, 4))"
7
to make things convenient, we can modify foo/__init__.py
to import both adder
functions:
from .pylib import pyadd
from .clib import cadd
rebuild and reinstall; then our test becomes even simpler:
# python3 -c "import foo; print(foo.pyadd(3, 4))"
7
# python3 -c "import foo; print(foo.cadd(3, 4))"
7