Ramiro Magno
Ramiro Magno

Reputation: 3175

Passing a vector or matrix from R to a C function using Rcpp without a local copy?

Here's an illustration of what I am currently doing with two functions.

In both cases I am creating a local copies: either an instance of std::vector<GLfloat> or of std::vector<GLdouble>.

Isn't there a shortcut not involving copies, where I could go from Rcpp::NumericMatrix to GLfloat */GLdouble * in a more direct way?

#include <Rcpp.h>
#include <GLFW/glfw3.h>
using namespace Rcpp;

//' @export
// [[Rcpp::export("glLoadMatrixf")]]
void gl_load_matrixf(Rcpp::NumericMatrix m) {

  std::vector<GLfloat> float_v = Rcpp::as<std::vector<GLfloat> >(m);
  const GLfloat * _float_v = &float_v[0];

  glLoadMatrixf(_float_v);
}

//' @export
// [[Rcpp::export("glLoadMatrixd")]]
void gl_load_matrixd(Rcpp::NumericMatrix m) {

  std::vector<GLdouble> double_v = Rcpp::as<std::vector<GLdouble> >(m);
  const GLdouble * _double_v = &double_v[0];

  glLoadMatrixd(_double_v);
}

Upvotes: 4

Views: 336

Answers (1)

Ralf Stubner
Ralf Stubner

Reputation: 26823

On my system GLfloat and GLdouble are defined as:

typedef float GLfloat;
typedef double GLdouble;

And R's numeric data type is always a double. So you can use &m[0] or m.begin() directly to get something convertible to a GLdouble * without the need to copy the data. For GLfloat this is not possible, since it requires a (lossy) cast to go from the (64 bit) double used by R to a (32 bit) float.

Some code as illustration:

Sys.setenv(PKG_LIBS="-lGL -lglfw")

Rcpp::sourceCpp(code = '
#include <Rcpp.h>
#include <GLFW/glfw3.h>
using namespace Rcpp;

// [[Rcpp::export("glLoadMatrixd")]]
void gl_load_matrixd(Rcpp::NumericMatrix m) {

     const GLdouble * _double_v = &m[0];

     glLoadMatrixd(_double_v);
}
')


glLoadMatrixd(matrix(runif(10), 2, 5))

BTW, I have no idea what dimensions such a matrix should have. 2x5 is probably incorrect ...

Upvotes: 3

Related Questions