Zunächst einmal, ein Disclaimer: Ich benutze Rcpp die ganze Zeit. In der Tat, als (nachdem ich von der Zeit von Rcpp umbenannt worden war) RcppTemplate schon seit zwei Jahren verwaist und ohne Updates war, fing ich an, es unter seinem ursprünglichen Namen Rcpp zu führen (unter dem es zu RQuantLib beigetragen wurde). Das war vor ungefähr einem Jahr, und ich habe ein paar inkrementelle Änderungen vorgenommen, die Sie im ChangeLog dokumentiert finden.
Nun ist RcppTemplate erst nach 35 Monaten ohne Update oder Update zurückgekommen. Es enthält interessanten neuen Code, aber es scheint, dass es nicht abwärtskompatibel ist, also werde ich es nicht verwenden, wo ich bereits Rcpp verwendet habe.
Rcppbind war nicht sehr aktiv gepflegt, wenn ich überprüft habe. Whit Armstrong hat auch ein Template-Interface-Paket namens rabstraction.
Inline ist etwas ganz anderes: Es vereinfacht den Kompilierungs-/Verbindungszyklus, indem es Ihr Programm als eine R-Zeichenkette "einbettet", die dann kompiliert, verknüpft und geladen wird. Ich habe mit Oleg darüber gesprochen, Inline Support Rcpp zu haben, was nett wäre.
Swig ist auch interessant. Joe Wang hat dort großartige Arbeit geleistet und die gesamte QuantLib für R eingepackt. Aber als ich es das letzte Mal probiert habe, funktionierte es nicht mehr wegen einiger Änderungen in R Internals. Laut einem Mitglied des Swig-Teams könnte Joe immer noch daran arbeiten. Das Ziel von Swig ist ohnehin, größere Bibliotheken zu haben. Dieses Projekt könnte wahrscheinlich mit einem Revival funktionieren, aber es ist nicht ohne technische Herausforderungen.
sollten weitere Erwähnung RInside gehen, die mit RCPP arbeitet und lässt Sie R innerhalb von C++ Anwendungen einbetten.
Um es zusammenzufassen: Rcpp funktioniert gut für mich, vor allem für kleine explorative Projekte, wo Sie nur eine oder zwei Funktionen hinzufügen möchten. Der Fokus liegt auf der Benutzerfreundlichkeit und erlaubt es Ihnen, einige der R-Interna zu "verstecken", die nicht immer Spaß machen. Ich kenne eine Reihe anderer Benutzer, denen ich per E-Mail geholfen habe. Also würde ich sagen, gehen Sie für diesen.
Meine Tutorials 'Intro zu HPC mit R' haben einige Beispiele für Rcpp, Rinside und Inline.
Edit: Also schauen wir uns ein konkretes Beispiel an (aus den "HPC with R Intro" Dias genommen und von Stephen Morborrow geliehen, der es von Venables und Ripley nahm). Die Aufgabe besteht darin, alle möglichen Kombinationen der Determinante einer 2x2-Matrix aufzulisten, die an jeder Position nur einzelne Ziffern enthält. Dies kann auf clevere vectorized Arten erfolgen oder mit roher Gewalt (wie wir in den Tutorial Dias diskutieren) wie folgt:
#include <Rcpp.h>
RcppExport SEXP dd_rcpp(SEXP v) {
SEXP rl = R_NilValue; // Use this when there is nothing to be returned.
char* exceptionMesg = NULL; // msg var in case of error
try {
RcppVector<int> vec(v); // vec parameter viewed as vector of ints
int n = vec.size(), i = 0;
if (n != 10000)
throw std::length_error("Wrong vector size");
for (int a = 0; a < 9; a++)
for (int b = 0; b < 9; b++)
for (int c = 0; c < 9; c++)
for (int d = 0; d < 9; d++)
vec(i++) = a*b - c*d;
RcppResultSet rs; // Build result set to be returned as list to R
rs.add("vec", vec); // vec as named element with name 'vec'
rl = rs.getReturnList(); // Get the list to be returned to R.
} catch(std::exception& ex) {
exceptionMesg = copyMessageToR(ex.what());
} catch(...) {
exceptionMesg = copyMessageToR("unknown reason");
}
if (exceptionMesg != NULL)
Rf_error(exceptionMesg);
return rl;
}
Wenn Sie diese speichern, wie, sagen wir, dd.rcpp.cpp
und haben Rcpp installiert, dann verwenden Sie einfach
PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'` \
PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'` \
R CMD SHLIB dd.rcpp.cpp
zum Erstellen einer gemeinsam genutzten Bibliothek. Wir verwenden Rscript
(oder r
), um Rcpp über seine Header- und Bibliotheksspeicherorte zu stellen. Einmal gebaut, können wir dies aus R laden und verwenden Sie wie folgt vor:
dyn.load("dd.rcpp.so")
dd.rcpp <- function() {
x <- integer(10000)
res <- .Call("dd_rcpp", x)
tabulate(res$vec)
}
Auf die gleiche Weise können Sie Vektoren senden, matrics, ... verschiedener R und C++ Datentypen zurück mit Leichtigkeit Ende her. Hoffe das hilft etwas.
Edit 2 (etwa fünf Jahre später +):
Also diese Antwort bekam gerade einen upvote und damit in meiner Warteschlange sprudelte. A Los der Zeit ist vergangen, seit ich es geschrieben habe, und Rcpp hat viel reicher in Funktionen bekommen. Also schrieb ich sehr schnell diese
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::IntegerVector dd2(Rcpp::IntegerVector vec) {
int n = vec.size(), i = 0;
if (n != 10000)
throw std::length_error("Wrong vector size");
for (int a = 0; a < 9; a++)
for (int b = 0; b < 9; b++)
for (int c = 0; c < 9; c++)
for (int d = 0; d < 9; d++)
vec(i++) = a*b - c*d;
return vec;
}
/*** R
x <- integer(10000)
tabulate(dd2(x))
*/
, die verwendet werden können, wie folgt mit dem Code in einer Datei /tmp/dd.cpp
R> Rcpp::sourceCpp("/tmp/dd.cpp") # on from any other file and path
R> x <- integer(10000)
R> tabulate(dd2(x))
[1] 87 132 105 155 93 158 91 161 72 104 45 147 41 96
[15] 72 120 36 90 32 87 67 42 26 120 41 36 27 75
[29] 20 62 16 69 19 28 49 45 12 18 11 57 14 48
[43] 10 18 7 12 6 46 23 10 4 10 4 6 3 38
[57] 2 4 2 3 2 2 1 17
R>
Einige der wichtigsten Unterschiede sind:
- einfacher zu bauen: einfach
sourceCpp()
es; auch führt R-Test-Code am Ende
- vollwertiges
IntegerVector
Typ
- Ausnahmebehandlung Wrapper automatisch von
sourceCpp()
Code-Generator hinzugefügt
Danke für die Antwort! Können Sie in RcppTemplate erklären, was Sie unter "interessanter neuer Code" verstehen? Wie unterscheidet sich das Paket von Rcpp? Ich weiß fast nichts über C++, wie funktioniert dieses Paket? – Peter
Dirk, vielleicht ist es Zeit für die referierte schnelle Vignette darüber, C++ mit R zu arbeiten ... :(! – knguyen
Es ist nicht leicht zu erklären, wie sie sich unterscheiden ... in C++, dass sie sich unterscheiden –