Hi Wayne, On 26 January 2011 at 17:56, wayne.zh...@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@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@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@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 | e...@debian.org | http://dirk.eddelbuettel.com ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel