This page looks best with JavaScript enabled

Python and C integration using Swig

 ·  ☕ 3 min read

Introduction

In terms of increasing performace of software there are generally 3 strategies:

  • Improve your algorithm’s efficiency.
  • Parallelize the algorithm.
  • Switch to a better performing language.

On this post we are going to focus on the last one. In general terms interpreted languages like Python tend to be slower than compiled ones like C. Since those are one of the most well know and used languages I’m gonna use those two.

There are several ways of accomplish such thing as stated in this answer from stackoverflow. Since the one option I already knew beforehand was Swig I decided to use it for this post.

Setup

Is easy to create a sample library to import from our python code as long as you follow their documentation. However here are the steps:

  1. Create the C library:
    • Add the following to example.c:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      #include "example.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);
          }
      }
      
    • Also create a header file example.h:
      1
      
      int fact(int n);  
      
  2. Create the SWIG interface file named example.i:
%module example

%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}

int fact(int n);
  1. Now we can use swig to build the python module:
swig -python example.i
  1. Lastly we have to compile it:
gcc -O2 -fPIC -c example.c
gcc -O2 -fPIC -c example_wrap.c -I/usr/include/python3.9
gcc -shared example.o example_wrap.o -o _example.so
  1. Now we can test that it can be imported from python:
python3 -c 'import example; print(example.fact(5))'
120

Benchmark

As the main reason to mix this two languages was to boost the performance, thought that was a must to try out how much of a difference we could get in terms of efficiency.

So used two different algorithms with the same implementation in both C and python, then used timeit to check how much time it takes for each of them.

Used the algorithm included in the official documentation to calculate factorial numbers. The second algorithm checks if two strings are anagrams also to verify if was hard to integrate strings usage with Swig.

Created a github repository with the source code. Here is the result of the benchmarks:

python3 benchmark.py 
Factorial benchmark:
c_time=9.265873008000199
py_time=10.641659813998558
Anagram benchmark:
c_time=9.163944766001805
py_time=141.76448946099845

On the factorial which is a simple algorithm there is some difference but may be not worth the time of making such integration. On the other side for the other algorithm the difference is notorious.

To conclude if your aim is to increase the performance of your software this is a good solution but due to the difficulty of the approach you may want to look first at the other two options mentioned at the start of this post.

Share on

ITasahobby
WRITTEN BY
ITasahobby
InTernet lover