Better idiom for filling a C++ array from a NumericVector

c++, r, rcpp

Solution

Ari, in the previous answer, John makes a good point. To extend a little, there are a few issues here

- you are dealing with a library with antiquated coding standard which wants a `double[]` or `*double`

- you want to use better coding standards and take advantage of Rcpp.

Well, fear not, we have a simple solution. Instantantiate the `Rcpp::NumericVector X(weightvec);` as usual, and then pass it to your function `foo()` (or whatever) as

foo(X.begin())

which gives you the required `double*`, and if needed `X.size()` provides the length. Because you come from R, you do not need to worry about scope and lifetime as you return to R afterwards.

In case you need to be more explicit, I have also used the uglier `&(X[0])`.

Also, the `Rcpp::as<>()` caster also works on `std::vector<double>`, so you can do

std::vector<double> x = Rcpp::as<std::vector<double> >(weightvec);

but apart from converting to C++ types it gains nothing here.

Finally, in case Josh or other C diehards are nearby, all this uses the fact that the `SEXP` you from R is guaranteed to have the contiguous C pointer, so you could also go via the very old school `REAL(weightvec)`.

Problem

I am using `Rcpp` to wrap an algorithm written (not by me) in C-like C++ (no STL, no boost, no nothing, as far as I can tell). You can see the implemented algorithm here (I'm wrapping `kmeans_w_03`). Consequently I'm passing in a `numeric` vector from R, which then needs to be converted to a `double` array. Currently I'm looping element-by-element and filling the one from the 'tother, like this: ``` SEXP testfn(SEXP weightvec, SEXP cluster_num_k){ Rcpp::NumericVector weightR(weightvec) ; int point_num = weightR.size(); double weight[point_num] ; for(int i = 0; i < point_num; ++i) { weight[i] = weightR[i]; } } ``` But with single-element numeric vectors, I can take advantage of Rcpp's beautiful `as` casting functionality: ``` int cluster_num = Rcpp::as<int>(cluster_num_k); ``` Trying something similar for length > 1 numeric vectors, however, leads to a crash or an error, depending on the exact variant of the syntax: ``` double weight[point_num] = Rcpp::as<double>(weightvec); ``` I don't necessarily mind the loop, but I'm a total neophyte and suspect there's a better way. I've read through Rcpp-introduction, hadley's wiki tutorial, and RcppExamples and not yet found anything that addresses this question, but that doesn't mean I didn't just miss it. My read of the Doxygen Rcpp docs is that `as` can cast to a STL vector but not an array (but I have a very hard time reading those docs, so I suspect I'm wrong there). If so, I guess I could cast to a vector and thence to an array.... So my question: is there a better (fewer lines of code, more expressive code, and perhaps even able-to-avoid-a-memory-allocation) way to convert a `NumericVector` to a `double[]`?

Original source