SWIG Introduction

SWIG is short for Simplified Wrapper and Interface Generator, a development tool that links C and C++ programs with various other high-level languages such as Perl, Python, Ruby and Tcl.

Languages currently supported.

  • C# – Mono
  • C# – MS.NET
  • D
  • Go language
  • Guile
  • Java
  • Javascript – Node.js
  • Javascript – V8
  • Javascript – WebKit
  • Lua
  • MzScheme/Racket
  • OCaml
  • Octave
  • Perl
  • PHP
  • Python
  • R
  • Ruby
  • Scilab
  • Tcl/Tk

SWIG with Python

With SWIG, Python can realistically do the following.

  • Call C/C++ libraries with Python
  • Inherit C++ classes with Python and use that inherited class in Python

To understand how the scripting language interacts with C/C++, let’s first briefly talk about the standard implementation of Python, CPython. The standard parser implementation of Python is written in C, and the base function modules are also written in C, which are then compiled into a Python parser and related so, so for CPython, its own parsing process is ultimately performed by executing The underlying C code is used to implement it. The official standard CPython provides corresponding APIs to allow extensions to Python. CPython extensions require embedding many of the APIs in <Python.h> in C/C++ code, and in order to be able to call C/C++ functions, you need to declare how to call the functions, type conversion of parameters, etc., which is very troublesome.

The purpose of SWIG is to provide scripting language interfaces for C/C++ APIs. All SWIG does is to solve the problem of scripting language and C/C++ interaction, and what SWIG does is actually two things.

  • Generate Wrapper functions based on the C API to be called, as glue to allow the scripting parser to interact with the underlying C functions.
  • Generate a calling interface to the scripting language for the generated Wrapper functions.

After completing the generation of the scripting language interface for the C/C++ functions, the corresponding Wrapper function is called by directly using the scripting language interface. The Wrapper function takes the arguments passed in by the scripting language, converts them into C arguments, and then calls the corresponding C interface, and after execution, the Wrapper function takes the results returned by C and converts them into the scripting language data type to return to the script upper layer.

SWIG installation

Windows

Installing SWIG is very simple, you only need to go to the official download and configure the environment variables.

Linux

1
2
3
4
5
6
wget http://prdownloads.sourceforge.net/swig/swig-4.0.1.tar.gz
tar -zxvf swig-4.0.1.tar.gz
cd swig-4.0.1
./configure
make
sudo make install

After installation, you need to add a path to .bashrc so that you can operate swig commands in any directory.

1
2
3
4
5
6
7
nano ~/.bashrc

# 添加以下两行到bashrc中
SWIG_PATH=/usr/local/share/swig/4.0.1
PATH=$PATH:$SWIG_PATH

source ~/.bashrc

Use swig -version to confirm that the version is installed.

swig: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory

The problem is that when swig is used, the libpcre.so.1 file cannot be found, so we look for its location in the system as follows.

1
sudo find / -name libpcre.so.1

A query reveals that the files are in the subenvironments folder of anaconda at

1
2
/home/qw/anaconda3/lib/libpcre.so.1
/home/qw/anaconda3/pkgs/pcre-8.43-he6710b0_0/lib/libpcre.so.1

Solution: Create soft links

1
sudo ln -s /home/qw/anaconda3/lib/libpcre.so.1 /usr/lib/libpcre.so.1

C language example

Writing code files

1, write C header file example.h

1
int fact(int n);

2、 Write C source code example.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include "example.h"

int fact(int n) {
    if (n < 0) {
        return 0;
    }
    if (n == 0) {
        return 1;
    }
    else {
        return n * fact(n-1);
    }
}
  1. Write the interface file example.i
1
2
3
4
5
6
7
8
%module example

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

int fact(int n)
  • The name after %module is the name of the module being wrapped, and Python loads the program by this name.
  • The content added between %{…%} generally contains some function declarations and headers needed for this file.
  • The last section, which declares the functions and variables to be wrapped.

Generate Python modules using command-line calls to the Swig method

1
swig -python example.i

After execution, 2 new files will be generated: example_wrap.c, example.py

Generate dynamic libraries with distutils

Create a new setup.py with the following content.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from distutils.core import setup, Extension

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

setup(name='example',
      version='0.1',
      author="SWIG Docs",
      description="""Simple swig example from docs""",
      ext_modules=[example_module],
      py_modules=["example"],
      )

Compile to generate library files.

1
python setup.py build_ext inplace

For Linux, a file like _example.cpython-37m-x86_64-linux-gnu.so will be generated in the directory after execution

Test that the .so file can be called by python without any problems. Create a test.py file in the example directory. The contents of the file are

1
2
3
import example

print(example.fact(4))

After that, execute python . /test.py to see if the output works.

If it is Windows, it will generate a file like _example.cp37-win_amd64.pyd in the directory. The call method is slightly different.

1
2
3
import _example

print(_example.fact(4))