Replies: 1 comment 2 replies
-
Dear @WKarel, these sound like pretty severe flaws. Yes, a PR with fixes would be more than welcomed. You could
I don't really use Eigen myself and just created the caster for the convenience of others. But this also means that it's not that well tested with regards to all of the various corner cases. Help is definitely welcome. |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
type_caster<Eigen::Ref...
> owns atype_caster<Eigen::Map...>
, which owns atype_caster<ndarray...>
.type_caster<Eigen::Ref...>::from_python
calls itstype_caster<Eigen::Map...>
, which in turn calls itstype_caster<ndarray...>
, which callsndarray_import
to do its job.If
ndarray_import
gets adltensor
of matching properties, it creates a view into the memory of the Python instance.Otherwise (e.g. if the dtype does not match), it copy-converts the data if called with convert=true, or it returns nullptr, making from_python return false.
The latter works if
Eigen::Ref<...>
is used as function argument, because the type_caster is kept alive until the bound function returns, and so the memory owned by the temporary ndarray is valid during the bound function call.When
static constexpr bool IsClass = false;
is inserted into
type_caster<Eigen::Ref...>
, thencast<Eigen::Ref...>(handle)
compiles. However, the type_caster then is a temporary withincast
, which is destroyed upon returning fromcast
. Hence, ifndarray_import
does a conversion, the result ofcast
points to invalid memory.type_caster<Eigen::Ref...>
andtype_caster<Eigen::Map...>
really supposed to not definebool IsClass
? Thencast<Eigen::Ref...>
andcast<Eigen::Map...>
do not compile, which is a pity.type_caster<Eigen::Map...>::from_python
would need to disallow conversions bytype_caster<ndarray...>::from_python
. This would affect the treatment of bound function arguments, too. Even better I would find more fine-grained type_caster specializations forEigen::Ref
. WhileEigen::Ref<const T...>
maps data as well, it can also own that data, meaning that it could own the result of conversions, as is the case in pybind11.Also, there are quite obvious flaws in
type_caster<Eigen::Map>::strides()
:caster.value.stride(1)
even if the ndarray has less than 2 dimensions.StrideType::InnerStrideAtCompileTime
andStrideType::OuterStrideAtCompileTime
can be 0, meaning contiguous memory to Eigen. In this common case (e.g. default ofEigen::Map
),StrideType
must not be initialized with 0s, but with the respective stride values for contiguous memory, or be default-constructed, to avoid assertions failing in Eigen.Concerning the type_caster specializations for Eigen types in general, they specialize for all scalar types, even though they handle only those that can be handled by dlpack (static_assert in
dtype<T>()
. I would advocate for SFINAE-limiting them to the scalar types they can actually handle, so users may provide specializations for their custom types.Would a pull request be welcome?
Demonstration code:
C++:
Python:
Beta Was this translation helpful? Give feedback.
All reactions