Betrachten Sie 1) eine benutzerdefinierte Klasse mit einem potenziell großen Speicherdruck und 2) eine Funktion der obersten Ebene, die eine Vorverarbeitung durchführt und dann ein neues Objekt unserer benutzerdefinierten Klasse erstellt und zurückgibt. Um unnötiges Kopieren nach Wert zu vermeiden, weist die Funktion das Objekt zu und gibt stattdessen einen Zeiger darauf zurück.
Basierend auf einer früheren Diskussion scheint es, dass der richtige Weg, einen Zeiger auf ein neu erstelltes Objekt zurückzugeben, darin besteht, es mit einem Wrap zu versehen Rcpp::XPtr<>
. R sieht es dann jedoch effektiv als externalptr
, und ich kämpfe darum, den richtigen Weg zu finden, um es mit der Moderne RCPP_EXPOSED_CLASS
und der RCPP_MODULE
Art und Weise, Dinge zu tun, zu besetzen.
Die Alternative besteht darin, den Rohzeiger zurückzugeben. Aber dann bin ich nicht 100% sicher, dass der Objektspeicher richtig bereinigt wird. Ich lief valgrind
, um auf Speicherlecks zu testen, und es wurden keine gefunden. Doch wer räumt auf? R?
test.cpp
#include <Rcpp.h>
// Custom class
class Double {
public:
Double( double v ) : value(v) {}
double square() {return value*value;}
private:
double value;
};
// Make the class visible
RCPP_EXPOSED_CLASS(Double)
// Option 1: returning raw pointer
Double* makeDouble( double x ) {
Double* pd = new Double(x);
return pd;
}
// Option 2: returning XPtr<>
SEXP makeDouble2( double x ) {
Double* pd = new Double(x);
Rcpp::XPtr<Double> ptr(pd);
return ptr;
}
RCPP_MODULE(double_cpp) {
using namespace Rcpp;
function( "makeDouble", &makeDouble );
function( "makeDouble2", &makeDouble2 );
class_<Double>("Double")
.constructor<double>("Wraps a double")
.method("square", &Double::square, "square of value")
;
}
In R.
Rcpp::sourceCpp("test.cpp")
d1 <- makeDouble(5.4) # <-- who cleans this up???
# C++ object <0x56257d628e70> of class 'Double' <0x56257c69cf90>
d1$square()
# 29.16
d2 <- makeDouble2(2.3)
# <pointer: 0x56257d3c3cd0>
d2$square()
# Error in d2$square : object of type 'externalptr' is not subsettable
Meine Frage ist, ob Rcpp::Xptr<>
es der richtige Weg ist, Zeiger zurückzugeben, und wenn ja, wie kann ich R dazu bringen, das Ergebnis als Double
nicht zu sehen externalptr
? Wenn das Zurückgeben eines Rohzeigers keine Speicherprobleme verursacht, wer bereinigt dann das von der Funktion erstellte Objekt?
CustomClass*
. Die eigentliche Anwendung ist eine benutzerdefinierte Datenstruktur ohne R-Äquivalent, und alle Interaktionen werden über die von der RCPP_MODULE
. Die engste Übereinstimmung, die meine motivierte Suche gefunden hat, war ein Beitrag von vor 7 Jahren , in dem ich anscheinend einen template <> CustomClass* as()
Konverter definieren muss . Ich bin mir jedoch nicht sicher, wie es mit RCPP_MODULE
und interagieren soll RCPP_EXPOSED_CLASS
, zumal ich dachte, dass letzteres bereits definiert ist wrap()
und as()
.
RCPP_EXPOSED_CLASS
und RCPP_MODULE
ist wirklich der Weg, um es zu tun? Ich habe das noch nie benutzt oder gesehen.
Rcpp::XPtr
einen externen Zeiger aus C ++ - Code erstellen. Und du willst es machendouble *
oder was auch immer deine Nutzlast ist. Hier, in der Galerie, bei GitHub sollte es Beispiele geben ... Vielleicht können Sie mit einer motivierten Suche etwas finden, das nah genug ist?