C Extension Module using Python - GeeksforGeeks

27 Mar, 2019
Writing a simple C extension module directly using Python’s extension API and no other tools. It is straightforward to make a handcrafted extension module for a simple C code. But first, we have to make sure that the C code has a proper header file.
Code #1 :
#include <math.h>  extern int gcd(int, int);extern int in_mandel(double x0, double y0, int n);extern int divide(int a, int b, int *remainder);extern double avg(double *a, int n);  typedef struct Point{    double x, y;} Point;  extern double distance(Point *p1, Point *p2);
 The header would correspond to a library that has been separately compiled. The code below illustrates the basics of writing extension functions, following this assumption.
Code #2:
# include "Python.h"# include "sample.h"  /* int gcd(int, int) */static PyObject * py_gcd(PyObject * self, PyObject * args){    int x, y, result;    if (! PyArg_ParseTuple(args, "ii", &x, &y))    {        return NULL;    }    result = gcd(x, y);    return Py_BuildValue("i", result);}  /* int divide(int, int, int *) */static PyObject * py_divide(PyObject * self, PyObject * args){    int a, b, quotient, remainder;    if (! PyArg_ParseTuple(args, "ii", &a, &b))    {        return NULL;    }    quotient = divide(a, b, &remainder);    return Py_BuildValue("(ii)", quotient, remainder);}
 Code #3 : Module method table and structure
/* Module method table */static PyMethodDef SampleMethods[] ={    {"gcd", py_gcd, METH_VARARGS, "Greatest common divisor"},    {"divide", py_divide, METH_VARARGS, "Integer division"},    { NULL, NULL, 0, NULL}};  /* Module structure */static struct PyModuleDef samplemodule ={    PyModuleDef_HEAD_INIT,    "sample", /* name of module */    "A sample module", /* Doc string (may be NULL) */    -1, /* Size of per-interpreter state or -1 */    SampleMethods /* Method table */};  /* Module initialization function */PyMODINIT_FUNCPyInit_sample(void){    return PyModule_Create(&samplemodule);}
 
Code #4: Creating a setup.py python file for building the extension module.
# setup.pyfrom distutils.core import setup, Extension  setup(name='sample',    ext_modules=[            Extension('sample',                    ['pysample.c'],                    include_dirs = ['/some/dir'],                    define_macros = [('FOO','1')],                    undef_macros = ['BAR'],                    library_dirs = ['/usr/local/lib'],                    libraries = ['sample']                    )            ])
 
Code #5: Now simply use python3 buildlib.py build_ext --inplace, to build the resulting library.
bash% python3 setup.py build_ext --inplace
running build_ext
building 'sample' extension
gcc -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
  -I/usr/local/include/python3.3m -c pysample.c
  -o build/temp.macosx-10.6-x86_64-3.3/pysample.o
gcc -bundle -undefined dynamic_lookup
build/temp.macosx-10.6-x86_64-3.3/pysample.o \
  -L/usr/local/lib -lsample -o sample.so
bash %

The above code will create a shared library called sample.so. Code #6 :
import sample  print ("gcd = ", sample.gcd(35, 42))  print ("\ndistance : ", sample.divide(42, 8))
Output :
gcd = 7

distance = (5, 2)

 “Extending and Embedding the Python Interpreter” is a Python’s documentation that can be consulted before attempting any kind of handwritten extension.
In extension modules, functions can be written as shown in code snippet below.
Code #4 :
static PyObject *py_func(PyObject *self, PyObject *args){    ...}
 
PyObject – C data type that represents any Python object. At a very high level, an extension function is a C function that receives a tuple of Python objects (in PyObject *args) and returns a new Python object as a result. The self argument to the function is unused for simple extension functions, but comes into play should you want to define new classes or object types in C.
The PyArg_ParseTuple() function is used to convert values from Python to a C representation. As input, it takes a format string that indicates the required values, such as “i” for integer and “d” for double, as well as the addresses of C variables in which to place the converted results.
Py_BuildValue() function is used to create Python objects from C data types. It also accepts a format code to indicate the desired type. In the extension functions, it is used to return results back to Python. One feature of Py_BuildValue() is that it can build more complicated kinds of objects, such as tuples and dictionaries.
Python-ctype
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Python Dictionary
How to Install PIP on Windows ?
Enumerate() in Python
Different ways to create Pandas Dataframe
Iterate over a list in Python
*args and **kwargs in Python
Reading and Writing to text files in Python
Create a Pandas DataFrame from Lists
Check if element exists in list in Python
How To Convert Python Dictionary To JSON?