Reputation: 59
Is it possible to define a pointer to a Eigen::Map object? The original code is quite complex but here is what I am trying to achieve (pseudo code)
void testfunction1(... XPtr){
// XPtr is a pointer
// create a vector, map it to a Map object and make XPtr point to the latter
VectorXd Xnew(9);
Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
Map<VectorXd> XnewMap(Xnew.data(), 9);
// make XPtr point to XnewMap so that Xnew data can be
// accessed outside testfunction1()
// ... how? I suspect this to involve some dynamic memory allocation
};
void testfunction2(bool yes){
// main function
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
const Map<VectorXd> X(XR.data(), 9); // yes the mapped version is needed
// create a pointer to X, say XPtr
// ... how?
if(yes){ // make XPtr point to XnewMap which is defined in testfunction1()
testfunction1(XPtr);
};
//... some computations
// make XPtr point again to X
// ... how?
};
Upvotes: 3
Views: 4185
Reputation: 29205
First of all no need to use pointers here because Map is already essentially a pointer, so it would be simpler so update the Map object with placement new. Nonetheless, your current design would require allocation within testfunction1 and deallocation within testfunction2 in case it has been allocated, which is not really safe. So better adopt a functional design by putting "some computations" within a function (or a named lambda), make testfunction1
return by value:
VectorXd testFunction1() { return Xnew; }
void testfunction2(bool yes){
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
const Map<VectorXd> X(XR.data(), 9);
auto func = [&] (Eigen::Ref<VectorXd> X) {
/* some computation */
}
if(yes) func(testfunction1());
else func(X);
};
If you really want to keep your current logic, then here is a self-contained example using placement new:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
void testfunction1(Map<VectorXd> &XMap){
double * Xnew = new double[9];
::new (&XMap) Map<VectorXd>(Xnew,9);
XMap << 10, 20, 30, 40, 50, 60, 70, 80, 90;
};
int main()
{
bool yes = true;
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
Map<VectorXd> X(XR.data(), 9);
if(yes) testfunction1(X);
// use X ...
cout << X.transpose() << endl;
// restore X and free memory allocated in testfunction1
if(yes){
delete[] X.data();
::new (&X) Map<VectorXd>(XR.data(),9);
}
cout << X.transpose() << endl;
}
which is pretty bad because it can leak if an exception is raised when using X. You could workaround manual memory management by asking testFunction1 to return a VectorXd
(or anything that handle memory allocation/deallocation on its own) and do the placement new in the main function:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
VectorXd testfunction1(){
VectorXd Xnew(9);
Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
return Xnew;
};
int main()
{
bool yes = true;
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
Map<VectorXd> X(XR.data(), 9);
{
VectorXd X2;
if(yes) {
X2 = testfunction1(); // shallow copy thanks to move semantic
::new (&X) Map<VectorXd>(X2.data(),9);
}
// use X ...
cout << X.transpose() << endl;
// restore X
::new (&X) Map<VectorXd>(XR.data(),9);
}
cout << X.transpose() << endl;
}
Finally, if the content of X
should be read-only, then use Map<const VectorXd>
and not const Map<VectorXd>
as in your initial question.
Upvotes: 1