 # Using C Codes in Python | Set 1

Let`s discuss the problem of accessing C code from Python. Because it is quite obvious that many of the built-in Python libraries are written in C. Thus, access to C is a very important part of Python`s interoperability with existing libraries. Python provides a rich API for programming in C, but there are many different ways to work with C.

Code # 1: [` work.c `] The C code we`re dealing with.

 ` # include & lt; math.h & gt; `   ` int ` ` gcd (` ` int ` ` x, ` ` int ` ` y) ` ` {` ` int g = y; ```` while (x & gt; 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 & lt; n; i + + )   { total + = a [i];  } return total / n;  }   typedef struct Point { double x, y;  } Point;    double distance (Point * p1, Point * p2) { return hypot (p1 - & gt; x - p2 - & gt; x, p1 - & gt; y - p2 - & gt; y);  } ```

The above code has various 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 the above code is in a file named work.c and compiled into a library that can be linked to other C code. We now have a number of C functions that have been compiled into a shared library. So, we call functions entirely from Python without the need to write additional C code or use a third-party extension tool.

Using ctypes:
Will play in Python ctypes , but make sure the C code 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.).

Also, the libsample.so file has been placed in the same directory as ` work.py ` Let`s get to the ` work.py ` now.

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

 ` # work. py ` ` import ` ` ctypes ` ` import ` ` os `   ` # find file & # 39; libsample .so & # 39; in ` ` # 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: Code Access

 ` # int gcd (int, int) ` ` gcd ` ` = _ mod.gcd ```` gcd.argtypes = (ctypes.c_int, ctypes.c_int) gcd.restype = ctypes.c_int   # int division (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 argument & # 39; double * & # 39; class DoubleArrayType:   def from_param ( self , param):   < p> 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): i f 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 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 you can easily load the module and use the resulting C functions. See the next part —