Introduction ============ 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. 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 ----------------------- :: // 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: :: // %{ #include "simple/object.h" %} // Comment out one line -------------------- :: // 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(); // In C#, string are immutable This same line will be transformed to the following line in the Swig input file: :: // std::string &get_name(); // 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. :: // int m_value = 0; … // The result in the Swig input file is: :: /* // int m_value = 0; … // */ 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: :: /* %apply std::string &OUTPUT … //*/ It will result in the following line in a Swig input file: :: // %apply std::string &OUTPUT … // To add only one line, a simpler form is also possible: :: // %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. See the examples in the git repo: - `pysimple.py `__ (Python wrapper) - `cssimple.py `__ (C# wrapper) 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). Call ``set_script_path(__file__)`` so relative paths resolve correctly. - **PySwig** — orchestrates parsing annotations, writing Swig ``.hh`` interface files, and optionally invoking Swig. Use ``PySwig(parse_cli=False)`` when configuring everything from a script. Typical workflow: 1. Create one or more ``FileConfig`` instances and register them on ``PySwig``. 2. Set module name, output directories, typemaps, and includes. 3. Call ``generate()`` to write Swig input files from annotated headers. 4. Configure language options and call ``run_swig()`` to produce wrapper sources. The lower-level **Swig** class locates the Swig executable and runs it with ``cwd=`` set to the output directory. **ProcessSrcFile** parses annotations in a single header; you rarely instantiate it directly. For command-line use, ``pyswig`` accepts optional header paths via ``PySwig.set_input_files()``; paths are resolved without changing the process working directory.