itQ
itQ

Reputation: 59

C++ eigen pointer to a Eigen::Map<Eigen::VectorXd> object

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

Answers (1)

ggael
ggael

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

Related Questions