[Rd] Dealing with R list objects in C/C++
Dirk Eddelbuettel
edd at debian.org
Thu Jan 27 03:07:01 CET 2011
Hi Wayne,
On 26 January 2011 at 17:56, Wayne.Zhang at barclayscapital.com wrote:
| Hi,
|
| I'd like to construct an R list object in C++, fill it with relevant data, and pass it to an R function which will return a different list object back. I have browsed through all the R manuals, and examples under tests/Embedding, but can't figure out the correct way. Below is my code snippet:
|
| #include <Rinternals.h>
| // Rf_initEmbeddedR and other setups already performed
|
| SEXP arg, ret;
|
| // this actually creates a pairlist. I can't find any API that creates a list
| PROTECT(arg = allocList(3));
|
| // I want the first element to be type integer, second double, and third a vector.
| INTEGER(arg)[0] = 1; // <- runtime exception: "INTEGER() can only be applied to a 'integer', not a 'pairlist'
| REAL(arg)[1] = 2.5; // control never reached here
|
| VECTOR_PTR(arg)[2] = allocVector(REALSXP, 4);
| REAL(VECTOR_PTR(arg)[2])[0] = 10.0;
| REAL(VECTOR_PTR(arg)[2])[1] = 11.0;
| REAL(VECTOR_PTR(arg)[2])[2] = 12.0;
| REAL(VECTOR_PTR(arg)[2])[3] = 13.0;
|
| PROTECT(call = lang2(install(entryPoint.c_str()), arg));
|
| ret = R_tryEval(call, R_GlobalEnv, &errorOccurred);
|
|
| I'll be grateful if you can point me to any online docs/samples.
This is a non-trivial problem when the use the C API provided by R. It is all
documented, but you need to study the 'Writing R Extensions' in some detail,
as well as maybe 'R Programming' by Gentleman and/or 'Software for Data
Analysis' by Chambers.
But there is another API you can use. It is provided by RInside (to embed R
inside C++) which uses Rcpp (for R and C++ integration). Install those two
packages from CRAN, and then drop the few lines below as a file, say,
wayne.cpp in the examples/standard/ directory of RInside. Saying 'make wayne'
will build an executable, using proper flags and linker options, and you can
run that:
edd at max:~/svn/rinside/pkg/inst/examples/standard$ make wayne
g++ -I/usr/share/R/include -I/usr/local/lib/R/site-library/Rcpp/include -I"/usr/local/lib/R/site-library/RInside/include" -O3 -pipe -g -Wall wayne.cpp -L/usr/lib64/R/lib -lR -lblas -llapack -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/local/lib/R/site-library/RInside/lib -lRInside -Wl,-rpath,/usr/local/lib/R/site-library/RInside/lib -o wayne
edd at max:~/svn/rinside/pkg/inst/examples/standard$ ./wayne
Showing list content:
L[0] 1
L[1] 2.5
L[2][0] 10
L[2][1] 11
Showing list content:
L[0] 42
L[1] 42
L[2][0] 10
L[2][1] 42
edd at max:~/svn/rinside/pkg/inst/examples/standard$
The code a list as you spec'ed with int, double and vector. The list is shown
on stdout, then passed to R, transformed by R and shown again at the C++ level.
Questions on RInside and Rcpp are welcome on the rcpp-devel list.
Hope this helps, Dirk
-----------------------------------------------------------------------------
#include <RInside.h> // for the embedded R via RInside
void show(const Rcpp::List & L) {
// this function is cumbersome as we haven't defined << operators
std::cout << "Showing list content:\n";
std::cout << "L[0] " << Rcpp::as<int>(L[0]) << std::endl;
std::cout << "L[1] " << Rcpp::as<double>(L[1]) << std::endl;
Rcpp::IntegerVector v = Rcpp::as<Rcpp::IntegerVector>(L[2]);
std::cout << "L[2][0] " << v[0] << std::endl;
std::cout << "L[2][1] " << v[1] << std::endl;
}
int main(int argc, char *argv[]) {
// create an embedded R instance
RInside R(argc, argv);
Rcpp::List mylist(3);
mylist[0] = 1;
mylist[1] = 2.5;
Rcpp::IntegerVector v(2); v[0] = 10; v[1] = 11; // with C++0x we could assign directly
mylist[2] = v;
show(mylist);
R["myRlist"] = mylist;
std::string r_code = "myRlist[[1]] = 42; myRlist[[2]] = 42.0; myRlist[[3]][2] = 42; myRlist";
Rcpp::List reslist = R.parseEval(r_code);
show(reslist);
exit(0);
}
-----------------------------------------------------------------------------
--
Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com
More information about the R-devel
mailing list