Open-source project
swig/swig avatar
swig/swig

SWIG: Generating C and C++ Bindings for Perl, Python, Java, Go and More

SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages.

6,327 stars1,316 forksSWIGNOASSERTION

At a glance

What is it?
SWIG is a compiler that reads annotated C or C++ headers and emits the glue code that makes those libraries callable from scripting and managed languages. It is a build-time code generator, not a runtime bridge, and the documentation is the real product.
Who is it for?
Adopt SWIG when one C or C++ library has to be reachable from several target languages and you can afford to maintain .i interface files alongside the headers. Do not adopt it when a single language is the only target and a hand-written extension module would be smaller, or when you need a runtime bridge that can call into C++ without a compile step.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly SWIG, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What SWIG actually solves for mixed-language codebases

The problem is the gap between a compiled library and a scripting or managed runtime. A C or C++ library exposes symbols and headers; Python, Perl, Ruby, PHP, Java, C#, Go, Lua, Tcl and the rest expect their own calling conventions, their own object model and their own type marshalling. Writing that adapter by hand means writing it once per language. The README describes SWIG as a compiler that integrates C and C++ with those languages, and the tagline lists Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, Octave, R, Scheme (Guile), Scilab and Ocaml as targets, with XML export of the parse tree as a separate output.

The intended user is the maintainer of a native library who is tired of maintaining parallel bindings, or a team that has to expose the same C++ code to a scripting layer for tooling and a managed layer for an application. SWIG does not replace the compiler or the interpreter. It sits before them in the build, producing source files that are then compiled and linked like any other module.

The .i file, the parse tree, and where the generated glue lands

The mechanism is front-end parsing followed by language-specific code emission. SWIG reads annotated C or C++ header files and produces wrapper code, which the README calls glue code. The annotations live in an interface file, conventionally with a .i extension, which is where you point SWIG at a header, declare what to wrap, and apply directives. The README also notes that SWIG can export its parse tree into XML, which is the escape hatch when you want to inspect or post-process what SWIG understood rather than what you hoped it understood.

Two consequences follow from this design. First, everything is decided at build time: the generated wrapper is ordinary C or C++ that you compile and link against the target interpreter or runtime, so there is no reflection layer and no runtime dispatch cost added by SWIG itself. Second, the interface file becomes a second source of truth next to the header. When the C++ signature changes, the .i file may need to change too, and nothing in the README suggests that drift is detected automatically. That is the real maintenance surface, and it is larger than the wrapper generation step itself.

Installing SWIG and running the first wrap

The README does not give a single install command. It points at Doc/Manual/Preface.html#Preface_installation for full instructions for Windows, Unix and Mac OS X using the release tarball or zip file, and at the INSTALL file for generic build and installation instructions on Unix. It also warns that building from the GitHub repository is a different procedure: the README says users wishing to build and install code from GitHub should visit https://swig.org/svn.html, because extra steps are required compared to building from the release tarball. Take that warning seriously; the repository layout includes autogen.sh and configure.ac, which is consistent with a bootstrap step being needed for a source checkout.

After building, the README's troubleshooting section is explicit that you must run make install, and that the install directory must be writable:

bash
make install

If SWIG cannot find its library files, the symptom described in the README is an error like this:

bash
$ swig foo.i
:1. Unable to find 'swig.swg'
:3. Unable to find 'tcl8.swg'

The README's prescribed diagnostic is to ask SWIG where it thinks its library lives:

bash
swig -swiglib

If that path is not what you expect, the README says you likely passed a bad option to configure, and that you should use ./configure --prefix=pathname to set the install location, taking care not to include a shell escape character such as ~ in the path. It also notes that the SWIG_LIB environment variable can override the library location, while adding that you really should not have to do this. For a first real use, the repository ships an Examples directory with per-language subdirectories including Examples/python/, Examples/java/, Examples/go/ and others, plus a browsable index at Examples/index.html. The README's stated route is to open that index in a browser rather than to follow a single canonical tutorial.

Where SWIG stops being the right tool

The README is candid about backwards compatibility: the developers strive to preserve it between releases, but the overriding aim is to provide the best wrapping experience, and where compatibility is known to be broken it is marked as an incompatibility in the CHANGES and CHANGES.current files. In practice that means a SWIG upgrade can change generated code in ways that require edits to your .i files or to your build, and the only advance notice is a changelog entry. A project that pins SWIG and never upgrades is trading away fixes; a project that tracks releases is signing up to read those files. The README points to a SWIG_VERSION preprocessor symbol for cases where you need to support more than one SWIG version at once, which is a workaround rather than a solution.

There are also cases where SWIG is simply the wrong shape. If your C++ API leans on templates, overload sets or ownership patterns that the target language cannot express, the generated glue will either flatten them or require manual typemaps, and the effort can exceed writing a focused binding by hand. If you only ever need one language, a dedicated binding generator or a hand-written extension module gives you a smaller artifact and no second interface file. And if you need to call into C++ without a code-generation and compile step, SWIG is not that: it produces source you must build, not a runtime bridge. The README names a bug tracker at https://www.swig.org/bugs.html and describes the known issues only as minor, without enumerating them.

SWIG versus hand-written extension modules

The obvious alternative is writing the binding yourself against the target language's native extension API. The difference is where the work lives. A hand-written module gives you exact control over marshalling, error translation and lifetime, and it produces one artifact for one language. SWIG gives you a declarative interface file and a generator that can emit for many languages from the same input, at the cost of an abstraction layer you do not fully control and a generator version you now depend on.

That trade is worth it when the language count is greater than one and the C++ surface is reasonably regular, because the marginal cost of adding a second or third target language is small. It is not worth it when the surface is irregular, because you will spend the time writing typemaps and %-directives anyway, and you will be debugging a generator's output rather than your own code. The README's own framing supports this reading: the stated overriding aim is the wrapping experience, which is a generator-first priority, not a hand-control-first one.

Maintenance cost, licence and what to check before upgrading

Maintenance has three parts. The generator itself moves; the last push to the repository was on 2026-09-17, and the README directs release-specific changes to CHANGES.current, older changes to CHANGES, and per-release summaries to RELEASENOTES. Your .i files are the second part, and they need review whenever the wrapped headers change. The third part is the generated code, which you generally do not edit but must rebuild.

Licensing needs care rather than a summary. The repository metadata reports the licence as NOASSERTION, and the tree contains LICENSE, LICENSE-GPL, LICENSE-UNIVERSITIES and COPYRIGHT as separate files. The README does not resolve this: it says to see the LICENSE file for details of the SWIG license, and directs anyone wanting further insight, including the licence of SWIG's output code, to https://www.swig.org/legal.html. That distinction matters because the terms covering the generator and the terms covering the code it emits are treated as separate questions. Read those files and that page before shipping generated wrappers; this is not a decision to make from a repository badge.

Editorial conclusion

Adopt SWIG when one C or C++ library has to be reachable from several target languages and you can afford to maintain .i interface files alongside the headers. Do not adopt it when a single language is the only target and a hand-written extension module would be smaller, or when you need a runtime bridge that can call into C++ without a compile step. Before committing, verify three things: that the release tarball path in Doc/Manual/Preface.html#Preface_installation matches your platform, that the language module you need is listed in the README tagline, and that your build can run swig -swiglib after make install so the library files resolve.

Frequently asked questions

What is Python SWIG?

It is SWIG used with Python as the target language: you point SWIG at an annotated C or C++ header, it emits wrapper code, and you compile that wrapper into a Python extension module. Python is one of the languages named in the README tagline, and Examples/python/ holds a worked example.

How did SWIG get popular?

The README does not discuss the project's history or adoption, so there is nothing in it to answer this from. What it does show is the scope that made it broadly applicable: one generator covering Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, Octave, R, Scheme (Guile), Scilab and Ocaml.

How do I install SWIG on Linux?

The README does not give a Linux-specific command. It points to Doc/Manual/Preface.html#Preface_installation for full instructions for Windows, Unix and Mac OS X using the release tarball or zip file, and to the INSTALL file for generic Unix build and installation instructions. Building from a GitHub checkout needs extra steps and is documented separately at https://swig.org/svn.html.

Why does swig foo.i report "Unable to find 'swig.swg'"?

The README attributes this to SWIG being incorrectly configured or installed, and says the first thing to check is that you ran make install and had write permission on the install directory. If that does not fix it, run swig -swiglib to see where SWIG thinks its library is, and correct the configure prefix if the path is wrong.

Does SWIG work with C++ as well as C?

Yes. The README describes SWIG as reading annotated C/C++ header files and creating wrapper code so that the corresponding C/C++ libraries are available to the listed languages, or so that C/C++ programs can be extended with a scripting language.

Official sources

  1. Issues
  2. Project website
  3. README
  4. swig/swig on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/swig-swig.svg)](https://hysenlabs.com/projects/swig-swig)