C Extension with Python

Goal

Python allows you to call a library developed in C/C++.


Requisite

  • GCC compiler to compile C code

  • Swig to compile C into C wrapper for python


Create a project directory.

$ mkdir project && cd project

Create a c header file - example.h (just one line)

int fact(int n);


Create a definition file - example.c

#include "example.h"

#include "stdio.h"


int fact(int n) {

if (n < 0){ /* This should probably return an error, but this is simpler */

return 0;

}

if (n == 0) {

return 1;

}

else {

/* testing for overflow would be a good idea here */

return n * fact(n-1);

}

}



int main(void){

int v = fact(10);

printf("Result: %d", v);

}


Create an interface file for Swig

%module example

%{

#define SWIG_FILE_WITH_INIT

#include "example.h"

%}


int fact(int n);


Lastly create a python distutils setup file - setup.py

#!/usr/bin/env python

"""

setup.py file for SWIG example

"""

from distutils.core import setup, Extension

# Underscore in the extension name is requirement of Swig.

example_module = Extension('_example', sources=['example_wrap.c', 'example.c'])

setup (name = 'example',

version = '0.1',

author = "SWIG Docs",

description = """Simple swig example from docs""",

ext_modules = [example_module],

py_modules = ["example"])


Check swig version

$ swig -version

SWIG Version 3.0.12

Compiled with clang++ [x86_64-apple-darwin18.0.0]

...


Check gcc version

$ gcc --version

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1

Apple LLVM version 10.0.0 (clang-1000.11.45.5)

Target: x86_64-apple-darwin18.2.0

...


Check python version

$ python --version

Python 3.6.6 :: Anaconda custom (64-bit)


Run swig utility to create the wrapper c files.

$ swig -python example.i


Run python dist setup tool to build the module

$ python setup.py build_ext --inplace


Call factorial function from python

$ python -c "import example; print(example.fact(10))"

3628800