问题
I have doubt. I know that it is possible to call from a cpp
file an R
function.
- But it is possible to compile that
cpp
file (that has an R function inside -from a package, for examplecaret
-) into a.so
ordll
? - If it is possible. How does having a chuck of
R
code inside works. Does the compiled code calls the R interpreter before it compiles or it does not need to?
Thanks in advance
回答1:
Yes, you can embed R inside of C or C++ application. The API is old, stable, somewhat documented and a little unwieldy. But it can be done.
Or you just use RInside which does everything for you -- and comes with eight (8) different example subdirectories containing dozens of worked and working examples. Here is (the core) of one (which is a little old, we may write it tighter now):
#include <RInside.h> // for the embedded R via RInside
#include <iomanip>
int main(int argc, char *argv[]) {
RInside R(argc, argv); // create an embedded R instance
std::string txt = // load library, run regression, create summary
"suppressMessages(require(stats));"
"swisssum <- summary(lm(Fertility ~ . , data = swiss));"
"print(swisssum)";
R.parseEvalQ(txt); // eval command, no return
// evaluate R expressions, and assign directly into Rcpp types
Rcpp::NumericMatrix M( (SEXP) R.parseEval("swcoef <- coef(swisssum)"));
Rcpp::StringVector cnames( (SEXP) R.parseEval("colnames(swcoef)"));
Rcpp::StringVector rnames( (SEXP) R.parseEval("rownames(swcoef)"));
std::cout << "\n\nAnd now from C++\n\n\t\t\t";
for (int i=0; i<cnames.size(); i++) {
std::cout << std::setw(11) << cnames[i] << "\t";
}
std::cout << std::endl;
for (int i=0; i<rnames.size(); i++) {
std::cout << std::setw(16) << rnames[i] << "\t";
for (int j=0; j<cnames.size(); j++) {
std::cout << std::setw(11) << M(i,j) << "\t";
}
std::cout << std::endl;
}
std::cout << std::endl;
exit(0);
}
Then:
edd@max:~/git/rinside/inst/examples/standard(master)$ make rinside_sample3
ccache g++ -I/usr/share/R/include -I/usr/local/lib/R/site-library/Rcpp/include -I/usr/local/lib/R/site-library/RInside/include -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -g -O3 -Wall -pipe -Wno-unused -pedantic -Wall rinside_sample3.cpp -Wl,--export-dynamic -fopenmp -L/usr/lib/R/lib -lR -lpcre -llzma -lbz2 -lz -lrt -ldl -lm -lblas -llapack -L/usr/local/lib/R/site-library/RInside/lib -lRInside -Wl,-rpath,/usr/local/lib/R/site-library/RInside/lib -o rinside_sample3
edd@max:~/git/rinside/inst/examples/standard(master)$ ./rinside_sample3
Call:
lm(formula = Fertility ~ ., data = swiss)
Residuals:
Min 1Q Median 3Q Max
-15.2743 -5.2617 0.5032 4.1198 15.3213
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 66.91518 10.70604 6.250 1.91e-07 ***
Agriculture -0.17211 0.07030 -2.448 0.01873 *
Examination -0.25801 0.25388 -1.016 0.31546
Education -0.87094 0.18303 -4.758 2.43e-05 ***
Catholic 0.10412 0.03526 2.953 0.00519 **
Infant.Mortality 1.07705 0.38172 2.822 0.00734 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 7.165 on 41 degrees of freedom
Multiple R-squared: 0.7067, Adjusted R-squared: 0.671
F-statistic: 19.76 on 5 and 41 DF, p-value: 5.594e-10
And now from C++
Estimate Std. Error t value Pr(>|t|)
(Intercept) 66.9152 10.706 6.25023 1.90605e-07
Agriculture -0.172114 0.0703039 -2.44814 0.0187272
Examination -0.258008 0.253878 -1.01627 0.315462
Education -0.87094 0.183029 -4.75849 2.4306e-05
Catholic 0.104115 0.0352579 2.95297 0.00519008
Infant.Mortality 1.07705 0.38172 2.82157 0.00733572
edd@max:~/git/rinside/inst/examples/standard(master)$
which shows that
- yes we can use R from C++
- yes we can have R report the result
- yes we can get them back to C++ too
As I said, there are dozens more examples. And no, it doesn't just magically compile R into your executable -- you need R installed and its shared libraries are called.
来源:https://stackoverflow.com/questions/35975927/c-and-r-create-a-so-or-dll