# Using C codes in Python | Set 1

Last Updated : 18 Mar, 2019

Prerequisite: How to Call a C function in Python

Let’s discuss the problem of accessing C code from Python. As it is very evident that many of Pythonâ€™s built-in libraries are written in C. So, to access C is a very important part of making Python talk to existing libraries. There is an extensive C programming API that Python provides but there are many different to deal with C.

Code #1 : [`work.c`] C-Code that we are dealing.

 `#include ` ` `  `int` `gcd(``int` `x, ``int` `y) ` `{ ` `    ``int` `g ``=` `y; ` `    ``while` `(x > ``0``) ` `    ``{ ` `        ``g ``=` `x; ` `        ``x ``=` `y ``%` `x; ` `        ``y ``=` `g; ` `    ``} ` `    ``return` `g; ` `} ` ` `  `int` `divide(``int` `a, ``int` `b, ``int` `*` `remainder) ` `{ ` `    ``int` `quot ``=` `a ``/` `b; ` `    ``*``remainder ``=` `a ``%` `b; ` `    ``return` `quot; ` `} ` ` `  `double avg(double ``*` `a, ``int` `n) ` `{ ` `    ``int` `i; ` `    ``double total ``=` `0.0``; ` `    ``for` `(i ``=` `0``; i < n; i``+``+``) ` `    ``{ ` `        ``total ``+``=` `a[i]; ` `    ``} ` `    ``return` `total ``/` `n; ` `} ` ` `  `typedef struct Point ` `{ ` `    ``double x, y; ` `} Point; ` ` `  `double distance(Point ``*` `p1, Point ``*` `p2) ` `{ ` `    ``return` `hypot(p1``-``>x ``-` `p2``-``>x, p1``-``>y ``-` `p2``-``>y); ` `} `

Above code has different C-programming features.

gcd()
divide() – returning multiple values, one through a pointer argument
avg() – performing a data reduction across a C array
Point and distance() – involve C structures.

Let’s assume that the code above is found in a file named work.c and it has been compiled into a library libsample that can be linked to other C code. Now, we have a number of C functions that have been compiled into a shared library. So, we call the functions entirely from Python without having to write additional C code or using a third-party extension tool.

Using ctypes :
Python ctypes will come to play but make sure the C code, that is to be converted, has been compiled into a shared library that is compatible with the Python interpreter (e.g., same architecture, word size, compiler, etc.).

Further the libsample.so file has been placed in the same directory as the `work.py`. Let’s understand `work.py` now.

Code #2 : Python module that wraps around resulting library to access it

 `# work.py ` `import` `ctypes ` `import` `os ` ` `  `# locating the 'libsample.so' file in the ` `# same directory as this file ` `_file ``=` `'libsample.so'` `_path ``=` `os.path.join(``*``(os.path.split(__file__)[:``-``1``] ``+` `(_file, ))) ` `_mod ``=` `ctypes.cdll.LoadLibrary(_path) `

Code #3 : Accessing code

 `# int gcd(int, int) ` `gcd ``=` `_mod.gcd ` `gcd.argtypes ``=` `(ctypes.c_int, ctypes.c_int) ` `gcd.restype ``=` `ctypes.c_int ` ` `  `# int divide(int, int, int *) ` `_divide ``=` `_mod.divide ` `_divide.argtypes ``=` `(ctypes.c_int, ctypes.c_int, ` `                    ``ctypes.POINTER(ctypes.c_int)) ` ` `  `_divide.restype ``=` `ctypes.c_int ` ` `  `def` `divide(x, y): ` `    ``rem ``=` `ctypes.c_int() ` `    ``quot ``=` `_divide(x, y, rem) ` `    ``return` `quot, rem.value ` ` `  `# void avg(double *, int n) ` `# Define a special type for the 'double *' argument ` `class` `DoubleArrayType: ` `    ``def` `from_param(``self``, param): ` `         `  `        ``typename ``=` `type``(param).__name__ ` `         `  `        ``if` `hasattr``(``self``, ``'from_'` `+` `typename): ` `            ``return` `getattr``(``self``, ``'from_'` `+` `typename)(param) ` `         `  `        ``elif` `isinstance``(param, ctypes.Array): ` `            ``return` `param ` `         `  `        ``else``: ` `            ``raise` `TypeError(``"Can't convert % s"` `%` `typename) ` ` `  `    ``# Cast from array.array objects ` `    ``def` `from_array(``self``, param): ` `        ``if` `param.typecode !``=` `'d'``: ` `            ``raise` `TypeError(``'must be an array of doubles'``) ` `         `  `        ``ptr, _ ``=` `param.buffer_info() ` `        ``return` `ctypes.cast(ptr, ctypes.POINTER(ctypes.c_double)) ` `         `  `    ``# Cast from lists / tuples ` `    ``def` `from_list(``self``, param): ` `        ``val ``=` `((ctypes.c_double)``*``len``(param))(``*``param) ` `        ``return` `val ` `     `  `    ``from_tuple ``=` `from_list ` `     `  `    ``# Cast from a numpy array ` `    ``def` `from_ndarray(``self``, param): ` `        ``return` `param.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) ` ` `  `DoubleArray ``=` `DoubleArrayType() ` `_avg ``=` `_mod.avg ` `_avg.argtypes ``=` `(DoubleArray, ctypes.c_int) ` `_avg.restype ``=` `ctypes.c_double ` ` `  `def` `avg(values): ` `    ``return` `_avg(values, ``len``(values)) ` ` `  `# struct Point { } ` `class` `Point(ctypes.Structure): ` `    ``_fields_ ``=` `[(``'x'``, ctypes.c_double), (``'y'``, ctypes.c_double)] ` `     `  `# double distance(Point *, Point *) ` `distance ``=` `_mod.distance ` `distance.argtypes ``=` `(ctypes.POINTER(Point), ctypes.POINTER(Point)) ` `distance.restype ``=` `ctypes.c_double `

Now, one can easily load the module and use the resulting C functions. See the next part – Using C codes in Python | Set 2.

Previous
Next