First steps

CARMA relies on Pybind11 for the generation of the bindings and casting of the arguments from Python to C++. Make sure you are familiar with Pybind11 before continuing on.

You can embed CARMA in a Pybind11 project using the CMake commands:

ADD_SUBDIRECTORY(extern/carma)
TARGET_LINK_LIBRARIES(<your_target> PRIVATE carma)

It is advised to use ADD_SUBDIRECTORY to incorporate CARMA as this provides an interface target, carma, that can be linked to your target. Using this target prevents an include order dependency, see CARMA target for details.

Warning

if you are not using CARMA’s cmake target you have to ensure that you include CARMA before Armadillo. Not doing so results in a compile error.

CARMA can provide Armadillo and or Pybind11 at compile time if desired, see Armadillo and Pybind11 details.

See Pybind11’s CMake build system documentation or CARMA’s examples for a start.

Build examples

The tests and examples can be compiled using CMake. CMake can be installed with pip install cmake, your package manager or directly from cmake.

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=. -DCARMA_BUILD_EXAMPLES=true  -DCARMA_BUILD_TESTS=true .. && make install

To run the tests you need to install pytest:

pip install pytest

and run:

ctest

To install carma, you have to define

-DCMAKE_INSTALL_PREFIX=/installation/path/directory

(default value is /usr/local)

The installation directory contains

include                  # carma headers
tests                    # carma tests with python module (if enabled using -DBUILD_TESTS=on)
examples                 # carma python examples with python module (if enabled using -DBUILD_EXAMPLES=on)

See section Examples for an overview of the conversion approaches.

Design Patterns

CARMA was designed with three patterns in mind: borrow, transfer ownership and view.

Borrow

You can borrow the underlying memory of a Numpy array using the arr_to_*(py::array_t<T>, copy=false). The Armadillo object should not be returned without a copy out. Use this when you want to modify the memory in-place. If the array is not well behaved, see Well behaved, the data is copied to well-behaved memory and swapped in place of the input array. If copy=true this is equivalent to the copy approach below.

Note

the size of the Armadillo object is not allowed change when you borrow, i.e. strict=true.

Transfer ownership

You can transfer ownership to Armadillo using steal or copy. After transferring ownership of the memory, Armadillo behaves as if it has allocated the memory itself, hence it will also free the memory upon destruction using Numpy’s deallocator.

Steal

If you want to take ownership of the underlying memory but don’t want to copy the data you can steal the array. The Armadillo object can be safely returned out without a copy. There are multiple compile time definitions on how the memory is stolen, see Configuration for details. If the memory of the array is not well-behaved a copy of the memory is stolen.

Note

the size of the Armadillo object is allowed change after stealing, strict=false.

Copy

If you want to give Armadillo full control of underlying memory but also want to keep Numpy as owner you should copy. The Armadillo object can be safely returned out without a copy. If the memory of the array is not well-behaved a copy of the memory is used instead.

Note

the size of the Armadillo object is allowed change after copying, strict=false.

View

If you want to have a read-only view on the underlying memory you can use arr_to_*_view. If the underlying memory is not well-behaved, excluding writeable, it will be copied.