Skip to main content

Generate Swig input files from annotated header files

Project description

PySwig

pipeline status

python 3.9 python 3.10 python 3.11 python 3.12

coverage report

Simple wrapper integration (Python × SWIG): integration matrix (updated after a green pipeline on master; preview on develop — see pages-domain.md).

SWIG is a great tool to generate wrappers very easily in various scripting languages of C/C++ libraries. But if you develop a C/C++ library and its wrapper at the same time, it has a significant flow: the necessity to create input files distinct from the source code of your library. The more extensive the library is, the biggest issue is to have to maintain virtually two sets of header files.

With PySwig, the source header files are annotated, allowing the automatic generation of the input files needed by Swig. With those input files, Swig can then create the sources of the wrapper. In this way, the maintenance effort is reduced to its minimum, since only one set of header files is needed.

Furthermore, PySwig can also take care of calling Swig to generate the wrapper. The result is a Python script, importing PySwig, and defining the operations to carry out. In the end, one just has to call this Python script to generate the Swig input files and call Swig to create the wrapper source files in one step.

Installation

Requires Python 3.9+ and SWIG on your PATH (or SWIG / ESYS_SWIG environment variables).

pip install pyswig
pyswig --help

For wrapper development (Swig provisioning, multi-Python test runs, environment setup):

pip install pyswig-dev
pyswig-dev setup
pyswig-dev test-all

The pyswig-dev package depends on pyswig (same version on PyPI). See docs/guides/packaging.md.

The pyswig CLI accepts optional header paths for single-file runs; full wrapper generation still requires a script with FileConfig (see Quick start below). Useful flags: --version, -q/--quiet, --run-swig, -l/--language, --copy-shadow.

For PySwig contributors working from a git clone:

pip install -e "packages/pyswig[contributor]" -e packages/pyswig-dev
pyswig-dev setup

Documentation

Quick start

Configure header files with FileConfig, drive generation with PySwig, then run SWIG:

import pyswig

file_config = pyswig.FileConfig()
file_config.set_input_dir("../include/simple")
file_config.set_base_inc_dir("simple")
file_config.set_source_files(["version.h", "object.h"])

pyswig_obj = pyswig.PySwig(parse_cli=False)
pyswig_obj.add_file_config(file_config)
pyswig_obj.set_module_name("simple")
pyswig_obj.set_src_output_dir("./pysimple")
pyswig_obj.set_inc_output_dir("../include/pysimplewrap")  # optional wrapper include
pyswig_obj.generate()
pyswig_obj.set_all_warnings()
pyswig_obj.set_process_cpp()
pyswig_obj.set_language("python")
pyswig_obj.run_swig()

See the full example in src/pysimple.py. Generated Swig files land in src/pysimple/ and include/pysimple/simple_inc.h; run python pysimple.py from src/ to refresh them (they are not committed).

Development

Supported test Python versions are listed in pyproject.toml under [tool.pyswig] test-python-versions. Simple wrapper integration tests use the pinned SWIG versions in [tool.pyswig] integration-swig-versions; missing binaries are downloaded to .cache/swig (Windows: portable swigwin zip, Linux/macOS: built from source when needed).

# One-time setup: finds uv, installs test Pythons, .venv, dev deps, pre-commit hooks
python scripts/setup_dev.py

# Run tests on every configured Python version (coverage on 3.11 only)
python scripts/test_all.py --write-badges

# Default venv only
.venv/bin/python -m pytest          # Linux/macOS
.venv\Scripts\python -m pytest      # Windows

# End-to-end simple wrapper tests (downloads/builds SWIG versions from pyproject.toml)
python -m pytest -q -m integration tests/test_integration_simple_wrapper.py

# Full integration matrix (same as CI; reads pyproject.toml)
python scripts/ci_integration_matrix.py

Commit messages and code style are enforced with pre-commit (ruff + gitlint). See docs/guides/commit-messages.md.

Annotations

The basic principle is to add XML-like annotations in comments to various effects: to comment out a line, or a block of code; to include some lines in the input files used by Swig; to add automatically include files.

Add source include file

//<swig_inc/>

Automatically add the include file to the Swig input file. As an example of usage of this annotation, the result in the Swig input file would be:

//<swig_inc>
%{
#include "simple/object.h"
%}
//</swig_inc>

Comment out one line

//<swig_out/>

This annotation is to comment out one line of source code in the Swig input file. See the line below as an example one line in a header file of a library.

std::string &get_name();   //<swig_out/>   In C#, string are immutable

This same line will be transformed to the following line in the Swig input file:

//     std::string &get_name();    //<swig_out/>   In C#, string are immutable

Commenting out a block of code

Often a block of code needs to be commented out. It can be done in this way.

//<swig_out>
    int m_value = 0;
    …
//</swig_out>

The result in the Swig input file is:

/* //<swig_out>
    int m_value = 0;
    …
//</swig_out> */

Add code specific to Swig

Often, it’s required to add code specific to Swig to handle templates, typemaps, director, etc. It can be done as follow:

/*<swig>
%apply std::string &OUTPUT …
//</swig>*/

It will result in the following line in a Swig input file:

//<swig>
%apply std::string &OUTPUT …
//</swig>

To add only one line, a simpler form is also possible:

//<swig/> %apply std::string &OUTPUT …

In the Swig input file, the line will look like the following:

%apply std::string &OUTPUT …

Build script

As mentioned earlier, PySwig can also be used to automate the creation of the wrapper by directly calling Swig. The simplest is to look at one of the examples provided in the git repo for the wrapper of the c++ library simple.

There are two Python classes to be aware of:

  • FileConfig — configuration for a set of annotated source headers (input dir, output dir, source list, include base path).
  • PySwig — orchestrates parsing annotations, writing Swig .hh interface files, and optionally invoking Swig. Use PySwig(parse_cli=False) when configuring everything from a script; omit that when driving generation from the command line.

The example script:

  1. Creates one or more FileConfig instances and registers them on PySwig.
  2. Sets module name, output directories, typemaps, and includes.
  3. Calls generate() to write Swig input files from annotated headers.
  4. Configures and calls run_swig() to produce the wrapper sources.

The lower-level Swig class locates the Swig executable and runs it with language and warning options. ProcessSrcFile parses annotations in a single header; you rarely instantiate it directly.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyswig-0.3.0.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyswig-0.3.0-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file pyswig-0.3.0.tar.gz.

File metadata

  • Download URL: pyswig-0.3.0.tar.gz
  • Upload date:
  • Size: 19.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for pyswig-0.3.0.tar.gz
Algorithm Hash digest
SHA256 6b1dfa532e4d15977445f2bbafeb2600c553f07b3b6c3082426ebe42150e244f
MD5 fa4ef11c4f385f12a3b8d64cabb6afe7
BLAKE2b-256 8cac9b78c6daa512a4768ffd86835e638dda3fb2b4c4f3b482176fcfe975cd68

See more details on using hashes here.

File details

Details for the file pyswig-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pyswig-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 20.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for pyswig-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 753b7971e8d415ce313783848cd0c0b4dddb5c97c8c5e9ef803160a02fcb2985
MD5 a9111cc61d2925591de3c28f4f99de20
BLAKE2b-256 95457fc2da2d793657e9073f91aa6a080694987489bbddc6267bf87a75a7b92b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page