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[]
?
If your question is how to COPY data from Rcpp::NumericVector
to C++ array, transform()
is a good answer. But if you want to get the inner array from Rcpp::NumericVector
, which does not include any copying, you can do exactly the same as the extracting array from std::vector
:
double* arr = &vec[0];
where vec is a Rcpp::NumericVector
.
Ari, in the previous answer, John makes a good point. To extend a little, there are a few issues here
double[]
or *double
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)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With