First steps

Shapes example

Tip

See Installation for how to obtain the examples.

Let us walk through examples/shapes, which contains a Rectangle class we want to wrap.

Rectangle.hpp

examples/shapes/src/cpp/primitives/Rectangle.hpp

class Rectangle : public Shape<2>
{
public:
  Rectangle(double width=2.0, double height=1.0);
  ~Rectangle();
  //...
};

We start by writing a YAML configuration file that lists the classes to wrap.

package_info.yaml

examples/shapes/wrapper/package_info.yaml

name: pyshapes
modules:
  - name: primitives
    classes:
      - name: Rectangle

This configuration describes the structure of the Python package we want to create: a package named pyshapes with a primitives module that includes the Rectangle class.

See also

See Configuration for the full list of configuration options.

To generate the wrappers for this example, run:

cd examples/shapes
cppwg src/cpp \
  --wrapper_root wrapper \
  --package_info wrapper/package_info.yaml \
  --includes src/cpp/geometry src/cpp/math_funcs src/cpp/primitives \
  --std c++17

This directs cppwg to:

  • Read the C++ source from src/cpp.

  • Write the generated wrappers to the wrapper directory.

  • Use the YAML configuration at wrapper/package_info.yaml.

  • Search the listed directories for header includes.

  • Parse the source against the C++17 standard.

See also

See Command-line usage for other command-line options.

This creates a directory for the primitives module at wrapper/primitives, containing the pybind11 wrapper for Rectangle as a .hpp and .cpp file:

Rectangle.cppwg.hpp

void register_Rectangle_class(pybind11::module &m);

Rectangle.cppwg.cpp

namespace py = pybind11;
void register_Rectangle_class(py::module &m)
{
  py::class_<Rectangle, Shape<2> >(m, "Rectangle")
    .def(py::init<double, double>(), py::arg("width")=2, py::arg("height")=1)
    //...
   ;
}

The directory also contains a wrapper for the primitives module itself, in which the Rectangle wrapper is registered:

primitives.main.cpp

PYBIND11_MODULE(_pyshapes_primitives, m)
{
  register_Rectangle_class(m);
  //...
}

To compile the example wrappers, run:

mkdir build && cd build
cmake ..
make

The compiled wrapper code can now be imported in Python:

from pyshapes import Rectangle
r = Rectangle(4, 5)

See also

  • See the rest of examples/shapes for the full set of generated wrappers.

  • See examples/cells for a more complex project.

Command-line usage

usage: cppwg [-h] [-w WRAPPER_ROOT] [-p PACKAGE_INFO] [-c CASTXML_BINARY]
             [-m CASTXML_COMPILER] [--std STD] [--castxml_cflags CASTXML_CFLAGS]
             [-i [INCLUDES ...]] [--overwrite] [-q] [-l [LOGFILE]] [-v] SOURCE_ROOT

Generate Python Wrappers for C++ code

positional arguments:
  SOURCE_ROOT           Path to the root directory of the input C++ source code.

options:
  -h, --help            show this help message and exit
  -w, --wrapper_root WRAPPER_ROOT
                        Path to the output directory for the Pybind11 wrapper code.
  -p, --package_info PACKAGE_INFO
                        Path to the package info file.
  -c, --castxml_binary CASTXML_BINARY
                        Path to the castxml executable.
  -m, --castxml_compiler CASTXML_COMPILER
                        Path to a compiler to be used by castxml.
  --std STD             C++ standard e.g. c++17.
  --castxml_cflags CASTXML_CFLAGS
                        Additional flags for the castxml clang frontend. Pass
                        values starting with "-" using "=" e.g.
                        --castxml_cflags="-Wno-deprecated".
  -i, --includes [INCLUDES ...]
                        List of paths to include directories.
  --overwrite           Force rewrite of all wrapper files, even if unchanged.
  -q, --quiet           Disable informational messages.
  -l, --logfile [LOGFILE]
                        Output log messages to a file.
  -v, --version         Print cppwg version.

Tips

  • Examples. Use examples/shapes or examples/cells as a starting point for your own project.

  • CastXML flags. To pass extra flags to the castxml clang frontend (e.g. to silence a diagnostic), use --castxml_cflags. Values starting with - must use =, e.g. --castxml_cflags="-Wno-deprecated".

  • Pybind11 docs. See the pybind11 documentation for help understanding the generated wrapper code.