C++ and R: Create a .so or .dll

雨燕双飞 提交于 2020-01-02 10:05:36

问题


I have doubt. I know that it is possible to call from a cppfile an Rfunction.

  • But it is possible to compile that cppfile (that has an R function inside -from a package, for example caret-) into a .soor dll?
  • If it is possible. How does having a chuck of Rcode 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!