SWIG (Simplified Wrapper and Interface Generator)
SWIG is a software development tool that facilitates connecting programs written in C and C++ with a variety of high-level programming languages, including Python. It works by generating 'wrapper' code that allows scripting languages to access underlying C/C++ code. The current version is 4.4.1, with releases focused on C/C++ standard improvements, expanded language support, and Python compatibility updates.
Warnings
- breaking SWIG 4.4.0 changed the default generation of static types to heap types and introduced multi-phase module initialization for modern Python wrappers. This might require adjustments in older build systems or specific configurations, especially for projects relying on specific Python C API internals.
- gotcha When importing multiple SWIG-generated modules using `from <module> import *`, you might encounter a name clash on the special `cvar` object used to access global variables. This means only the `cvar` from the last loaded module will be accessible directly.
- gotcha The generated Python shared library filename must precisely match the module name specified in the SWIG interface file (`%module <module_name>`), typically with a leading underscore (e.g., `_example.so` for `%module example`). A mismatch will lead to import errors.
- gotcha Memory leaks can occur when SWIG wraps C/C++ pointers to opaque types (e.g., `HWND*` on Windows) and doesn't find a corresponding destructor. SWIG treats them as raw pointers without proper memory management.
- gotcha Issues can arise when C++ callbacks pass references to parameters that are then accessed in Python. The underlying C++ type might not correctly align with the Python instance, leading to errors when attempting to access methods of the referenced object in Python.
Install
-
pip install swig -
sudo apt-get install swig -
brew install swig
Imports
- <module_name>
import <module_name>
Quickstart
/* C/C++ file: example.h */
#ifndef EXAMPLE_H
#define EXAMPLE_H
int fact(int n);
int my_mod(int x, int y);
#endif // EXAMPLE_H
/* C/C++ file: example.c */
#include "example.h"
int fact(int n) {
if (n < 0) return 0; /* Or handle error appropriately */
if (n == 0) return 1;
return n * fact(n - 1);
}
int my_mod(int x, int y) {
if (y == 0) return 0; /* Or handle error appropriately */
return x % y;
}
/* SWIG interface file: example.i */
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
int fact(int n);
int my_mod(int x, int y);
# Build and run steps in bash
# 1. Generate SWIG wrapper code
# swig -python -c++ example.i
# 2. Compile C/C++ source and SWIG wrapper
# g++ -c example.c example_wrap.cxx -I/usr/include/python3.10 -fPIC
# 3. Link into a shared library
# g++ -shared example.o example_wrap.o -o _example.so
# Python usage:
import example
print(f"Factorial of 5: {example.fact(5)}")
print(f"7 mod 3: {example.my_mod(7, 3)}")