Configuration reference
cppwg is driven by a YAML configuration file (passed with --package_info). It
describes a package made of one or more modules (each compiled to its own
extension), and the classes and free functions each module wraps.
name: pyshapes # package
modules:
- name: primitives # module -> _pyshapes_primitives extension
source_locations:
- src/cpp/primitives
classes:
- name: Rectangle # class
excluded_methods:
- GetArea
Option inheritance
Options fall into two groups:
Level-specific options are only meaningful at one level (e.g.
modulesat the package level,importsat the module level,name_overrideat the class level).Common options may be set at the package, module, or class level and inherit downwards: a value set on the package applies to every module and class unless a lower level overrides it. This lets you set, say,
smart_ptr_typeonce for the whole package.
The tables below mark common options accordingly.
Package options
Set at the top level of the file.
Option |
Type |
Default |
Description |
|---|---|---|---|
|
str |
|
Package name; prepended to every module’s extension name ( |
|
list |
– |
The modules to build. See Module options. |
|
bool |
|
If true, every wrapper includes a single shared header collection instead of its own headers. Turn off so each wrapper includes only what it needs. |
|
list |
|
C++ exception classes to translate into Python. See Exceptions. |
|
list |
|
Type-caster headers to auto-include by type. See Type casters. |
|
bool |
|
If true, omit C++ default argument values from the generated bindings. |
|
bool |
|
If true, skip redundant |
|
list[str] |
|
Glob patterns for the header files cppwg scans. |
|
list[str] |
|
Glob patterns for the source files cppwg scans (used for template-instantiation discovery). |
All common options may also be set here.
Module options
Each entry under modules:.
Option |
Type |
Default |
Description |
|---|---|---|---|
|
str |
|
Module name; the extension is |
|
list[str] |
|
Directories (relative to the source root) whose classes this module wraps. |
|
list |
|
Classes to wrap, or the string |
|
list |
|
Free functions to wrap, or |
|
list[str] |
|
Python modules to import at the start of this module, so their types are registered first. Required for cross-module inheritance. See Cross-module inheritance. |
|
list[str] |
|
Base-class names registered by an imported package, so cppwg will emit them as bases. See Cross-module inheritance. |
All common options may also be set here.
Class options
Each entry under a module’s classes:.
Option |
Type |
Default |
Description |
|---|---|---|---|
|
str |
– |
The C++ class name (required). |
|
str |
|
Python name for the class, if different from the C++ name. |
|
str |
|
Header to attribute the class to, when the class name does not match its file name. |
All common options may also be set here.
Common options
Settable at the package, module, or class level; they inherit downwards.
Option |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
|
Exclude the whole class from wrapping. |
|
list[str] |
|
Method names to skip. |
|
list[str] |
|
Skip any method/constructor with an argument type matching one of these. |
|
list[str] |
|
Skip any method with a return type matching one of these. |
|
list[str] |
|
Skip any constructor with an argument type matching one of these. |
|
list[list[str]] |
|
Skip a constructor whose full argument-type list matches an entry. |
|
list |
|
Explicit template instantiations to wrap. See Template instantiations. |
|
bool |
|
Auto-discover explicit instantiations from the source. See Template instantiations. |
|
dict |
|
Drop discovered instantiations by template-argument value. See Template instantiations. |
|
bool |
|
Auto-resolve headers for project types used in wrapped signatures. See Includes. |
|
list[str] |
|
Extra headers to add to the wrapper’s |
|
str |
|
Holder type declared for wrapped classes, e.g. |
|
str |
|
Default pybind11 |
|
str |
|
Default pybind11 |
|
str |
|
Path to a Python template that injects extra binding code. See Custom generators. |
|
str |
|
Text emitted at the top of each wrapper file (e.g. a licence header). |
|
list[str] |
|
Lines emitted before a class’s registration block. |
|
list[str] |
|
Lines emitted after a class’s |
CPPWG_SOURCEROOT in a path value (e.g. in custom_generator) is replaced with
the source root directory.
Selecting what to wrap
List classes and free functions explicitly under a module, or wrap everything
found in the module’s source_locations with the sentinel string CPPWG_ALL:
modules:
- name: all
source_locations:
- src/cpp
classes: CPPWG_ALL
free_functions: CPPWG_ALL
CPPWG_ALL must be the whole value — a list that merely contains it (e.g.
[CPPWG_ALL, Foo]) is treated as literal class names, not “wrap everything”.
Template instantiations
A templated class must be wrapped once per instantiation. There are two ways to select them; they can be combined.
Explicit: template_substitutions
List each instantiation as a signature (the template parameters) and the
replacement argument lists:
- name: AbstractElement
template_substitutions:
- signature: <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
replacement: [[1, 2], [2, 2], [2, 3], [3, 3]]
Each replacement’s length must match the parameter count.
Automatic: discover_template_instantiations
Set discover_template_instantiations: True to have cppwg find explicit
instantiations (e.g. template class Foo<2, 2>;) in the source .cpp files,
without hand-writing them. Instantiations declared through a macro are found via
CastXML; recovering a defaulted trailing template argument from such a macro
instantiation requires CastXML >= 0.6.0 (older versions drop it, e.g. naming
Foo<2, 2> as Foo<2>). See the MacroMesh class in examples/cells.
Discovery reads literal template class statements directly and only parses a
.cpp with CastXML when all of its instantiations are macro-generated. A file
that mixes literal and macro-generated instantiations is not fully
discovered — its macro-generated ones are missed — so configure those manually
with template_substitutions.
Filtering discovery: discover_arg_excludes
To stop discovery from wrapping instantiations you do not want (e.g. everything the source instantiates at a spatial dimension of 1), map a template-parameter name to the argument values to drop:
discover_arg_excludes:
DIM: [1]
ELEMENT_DIM: [1]
SPACE_DIM: [1]
A discovered instantiation is dropped when the argument bound to a listed
parameter is one of its values, so Foo<SPACE_DIM=1> is dropped but
Foo<SPACE_DIM=2> is kept. Matching is by parameter name, so a value that is
a spatial dimension for one parameter but incidental for another — e.g. a
trailing PROBLEM_DIM of 1 in Bar<2, 2, 1> — is only excluded where it is
actually named. Only discovered instantiations are filtered;
template_substitutions are always wrapped as written. A key may be the bare
parameter name (ELEMENT_DIM) or carry a leading type as a
template_substitutions signature spells it (unsigned ELEMENT_DIM).
Uninstantiated-dependency dropping
cppwg automatically drops a wrapped instantiation whose wrapped interface (a
non-excluded method or constructor) takes or returns a project template type
that is never instantiated — which would otherwise fail to link or import with
an undefined symbol. Each drop is logged, e.g.
Excluding Foo<1>: wrapped interface depends on uninstantiated type Bar<0>. This
typically happens at a dimensional boundary — a low-dimensional element (e.g.
Facet<1>) whose faces are a never-instantiated Facet<0>. To keep such a
class, instantiate its dependency (see Corner in examples/cells); otherwise
the drop leaves the safe instantiations wrapped (see Facet).
Excluding members
Several options drop members that cannot or should not be wrapped. Type matches are on the type as it appears in the C++ signature, as a whole token, case-sensitively, and namespace-qualified where applicable.
excluded: True— drop the whole class.excluded_methods— drop methods by name.return_type_excludes/arg_type_excludes— drop methods (and, for args, constructors) whose return/argument type matches.constructor_arg_type_excludes— drop constructors by an argument type (e.g. a mesh reference the constructor stores a raw pointer to).constructor_signature_excludes— drop a constructor by its full argument-type list, e.g.- [unsigned]to drop a single-unsignedconstructor.
Includes
Each non-common wrapper needs the headers for the types in its signatures. cppwg offers three complementary mechanisms so you rarely list headers by hand.
source_includes
Extra headers added verbatim to the wrapper’s #include block. A bare name
(Foo.hpp) is quoted; an angle-bracket string (<foo>) is emitted as-is.
auto_includes
A wrapped signature may use another project type whose definition the class’s
own header only forward-declares — e.g. a MeshFactory<MESH> whose
generateMesh() returns a PottsMesh it never #includes. Set
auto_includes: True (at any level; it inherits down and is off by default):
modules:
- name: mymod
classes:
- name: MeshFactory
auto_includes: True # resolves PottsMesh.hpp from the signature
cppwg scans each such class’s wrapped method/constructor signatures, plus the
template arguments of its instantiations (e.g. a Foo<Bar, DIM> needs Bar.hpp
even if Bar never appears in a method/constructor signature), and for every
project type it finds (a class defined under the module source_locations)
adds that class’s header. Only project types are resolved — library types
(std::, boost, PETSc, VTK, …) are left alone — and a type name defined in more
than one header is treated as ambiguous and left for a manual source_includes.
It is a no-op with common_include_file, and does not cover types that appear
only in hand-written custom_generator code. See the MeshFactory class in
examples/cells/dynamic/config.yaml.
Type casters
A wrapped signature may expose a type pybind11 cannot convert on its own (a PETSc
Vec, a VTK vtkSmartPointer<...>, a boost ublas c_vector), which needs a
type-caster header in the wrapper. List your casters once under
typecasters, each with the header and the types it handles:
typecasters:
- header: caster_petsc.h
types: [Vec, Mat]
- header: PybindVTKTypeCaster.h
types: [vtkSmartPointer]
- header: PybindUblasTypeCaster.hpp
types: [boost::numeric::ublas::c_vector]
cppwg adds a caster’s header to a wrapper only when that class’s wrapped
signatures actually use one of its types — and to no other wrapper, keeping
these heavy headers out of wrappers that do not need them (they are never added
to the shared header collection). Because matching is against the type as it
appears in the generated signature, spell each type as written there: as a
whole token, case-sensitively, and namespace-qualified (boost::numeric::ublas::c_vector,
not vector; Vec matches ::Vec but not c_vector). You still add the caster
directories to your build’s include paths. Free functions are not covered — a
free function using a caster type still needs the header added manually. See
examples/cells/dynamic/config.yaml.
A caster converts a type only at the call boundary (arguments and returns), not for a type stored in a container or as object state, and not for non-const reference (out-)parameters. Signatures using a caster type in one of those shapes still have to be excluded.
Cross-module and cross-package inheritance
A wrapped class can inherit from a base wrapped in a different module, as long
as that base is registered somewhere imported first. Opt in per module with
imports, which lists the Python modules to import at the start of the generated
module. Do not list a module in its own imports (a circular import).
cppwg only emits an external base when it can confirm the base is registered, to
avoid a py::class_<...> with an unregistered base (which fails at import). Two
cases:
Base wrapped in another module of the same package — detected automatically;
just import that module:
modules:
- name: primitives # defines the base class, e.g. Rectangle
- name: composites
imports:
- pyshapes.primitives._pyshapes_primitives
classes:
- name: Square # inherits Rectangle, wrapped in `primitives`
Base wrapped in another package (unknown to this cppwg run) — also list the
base class name under external_bases so cppwg knows it is registered by an
imported module (names match without template arguments, and with or without
namespace qualification):
modules:
- name: all
imports:
- ext_pkg._ext_mod
external_bases:
- AbstractFoo # MyFoo inherits AbstractFoo, wrapped in ext_pkg
classes:
- name: MyFoo
See the pybind11 docs on partitioning code over multiple extension modules.
Excluding inherited overrides
Set exclude_inherited_overrides: True (package level) to shrink wrappers.
cppwg then does not emit a binding for a method that merely overrides a virtual
already wrapped on a wrapped base class: pybind11 inheritance plus C++ virtual
dispatch already expose it through the base binding, so the derived .def is
pure duplication. The virtual trampoline is still generated, so Python
subclasses can still override the method.
A method is skipped only when a wrapped, non-class-excluded base declares a
virtual of the same name, argument types and const-ness (the return type is not
compared, so a covariant-return override still matches). It is kept when: the
base itself excludes the method from wrapping (by name or by type), the base is
in another module that is not imports-linked, or another same-name overload on
the class would still be bound (which would otherwise shadow the base). Off by
default.
Exceptions
To stop C++ exceptions from crashing the Python interpreter, list their class
names under exceptions. cppwg generates a pybind11 exception translator for
each. By default the message is read with what(); set message_method to use a
different accessor:
exceptions:
- name: Exception
message_method: GetMessage
This only applies to thrown C++ exceptions. Errors from C dependencies that use
return codes (e.g. a PETSc PetscErrorCode) are not caught unless the wrapped
C++ code converts them into a C++ exception first (for PETSc, via
PetscCallThrow() in a C++-exception build, or by checking the code and
throwing). See PetscUtils::ThrowPetscError in the cells example.