Skip to content

Conversation

jagerman
Copy link
Member

@jagerman jagerman commented Aug 3, 2016

Eigen::Ref is a common way to pass eigen dense types without needing a template, e.g. the single definition void func(const Eigen::Ref<const Eigen::MatrixXd> &x) is a useful signature to accept any double-coefficient matrix-like object/block/etc. (without needing the implementation in a template.)

The current pybind11 eigen support fails with internal errors if attempting to bind a function with an Eigen::Ref<...> argument because, while Eigen::Ref<...> satisfies the "is_eigen_dense" requirement, it can't compile if used: Eigen::Ref<...> itself is not default constructible, and so the argument loader can't default construct an std::tuple containing an Eigen::Ref<...>, which results in compilation failure.

This commit adds support for Eigen::Ref<...> arguments by giving it its own type_caster implementation which basically is just a wrapper around the type_caster for the referenced type with a unique_ptr storing the required Ref object (which itself references the wrapped type_caster).

There is, of course, no performance advantage for pybind11-using code of using Eigen::Ref<...>--we are allocating a matrix of the derived type when loading it--this is mainly about allowing pybind11 to bind transparently to C++ methods taking Eigen::Refs.

Eigen::Ref is a common way to pass eigen dense types without needing a
template, e.g. the single definition `void
func(Eigen::Ref<Eigen::MatrixXd> x)` can be called with any double
matrix-like object.

The current pybind11 eigen support fails with internal errors if
attempting to bind a function with an Eigen::Ref<...> argument because
Eigen::Ref<...> satisfies the "is_eigen_dense" requirement, but can't
compile if actually used: Eigen::Ref<...> itself is not default
constructible, and so the argument std::tuple containing an
Eigen::Ref<...> isn't constructible, which results in compilation
failure.

This commit adds support for Eigen::Ref<...> by giving it its own
type_caster implementation which consists of an internal type_caster of
the referenced type, load/cast methods that dispatch to the internal
type_caster, and a unique_ptr to an Eigen::Ref<> instance that gets
set during load().

There is, of course, no performance advantage for pybind11-using code of
using Eigen::Ref<...>--we are allocating a matrix of the derived type
when loading it--but this has the advantage of allowing pybind11 to bind
transparently to C++ methods taking Eigen::Refs.
@wjakob
Copy link
Member

wjakob commented Aug 3, 2016

This is great, thank you!

@wjakob wjakob merged commit 39ff2d0 into pybind:master Aug 3, 2016
@jagerman jagerman deleted the eigen-ref-args branch August 12, 2016 02:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants