Reputation: 113
I want to use Eigen3 on data coming from another library. An earlier answer by ggael indicates a way for Eigen::Matrix
to adopt preexsisting data with the new
keyword. However, this is not sufficient for me, because the resulting Matrix
still seems to acquire ownership of the data, meaning that it will free the data when going out of scope. To wit, this is a crasher if data
eventually gets deleted by the library it comes from:
void crasher(double* data, size_t dim)
{
MatrixXd m;
new (&m) Map<MatrixXd>(data,dim,dim); // matrix adopts the passed data
m.setRandom(); cout<<m<<endl; // manipulation of the passed data via the Matrix interface
} // data deleted by m => potential problem in scope of function call
I have come up with two workarounds:
void nonCrasher1(double* data, size_t dim)
{
MatrixXd m; // semantically, a non-owning matrix
const Map<const MatrixXd> cache(m.data(),0,0); // cache the original „data” (in a const-correct way)
new (&m) Map<MatrixXd>(data,dim,dim); // matrix adopts the passed data
m.setRandom(); cout<<m<<endl; // manipulation of the passed data via the Matrix interface
new (&m) Map<const MatrixXd>(cache); // re-adopting the original data
} // original data deleted by m
This is rather inconvenient because of the presence of cache
. The other is free from this problem:
void nonCrasher2(double* data, size_t dim) // no need for caching
{
MatrixXd m; // semantically, a non-owning matrix
new (&m) Map<MatrixXd>(data,dim,dim); // matrix adopts the passed data
m.setRandom(); cout<<m<<endl; // manipulation of the passed data via the Matrix interface
new (&m) Map<MatrixXd>(nullptr,0,0); // adopting nullptr for subsequent deletion
} // nullptr „deleted” by m (what happens with original data [if any]?)
However, here it’s unclear what happens with the original data of m
(if any – all this is not completely clear from the documentation of Eigen3).
My question is whether there is a canonical way for Eigen::Matrix
to release ownership of it’s data (self-allocated or adopted).
Upvotes: 3
Views: 1486
Reputation: 29225
In nonCrasher2
nothing happen to data, except that it has been filled with random values on purpose.
However, this still look like hackish, and the clean approach be to use a Map
object instead of MatrixXd
:
Map<MatrixXd> m(data, dim, dim);
m.setRandom();
If you need m
to be a MatrixXd
because you need to call functions taking MatrixXd
objects, and such functions cannot be templated, then you might consider generalizing these functions to take Ref<MatrixXd>
objects. By default, a Ref<MatrixXd>
can accept any expression which storage reassemble to a MatrixXd
with arbitrary leading dimension. It has been introduced in Eigen 3.2, check the doc for more details.
Upvotes: 1