Rozważ 1) klasę niestandardową z potencjalnie dużym drukiem pamięci oraz 2) funkcję najwyższego poziomu, która wykonuje wstępne przetwarzanie, a następnie tworzy i zwraca nowy obiekt naszej klasy niestandardowej. Aby uniknąć niepotrzebnego kopiowania według wartości, funkcja przydziela obiekt i zwraca do niego wskaźnik.
Na podstawie poprzedniej dyskusji wydaje się, że właściwym sposobem na zwrócenie wskaźnika do nowo utworzonego obiektu jest owinięcie go Rcpp::XPtr<>
. Jednak R następnie widzi to skutecznie jako externalptr
, i staram się znaleźć właściwy sposób, aby rzucić to na nowoczesność RCPP_EXPOSED_CLASS
i RCPP_MODULE
sposób robienia rzeczy.
Alternatywą jest zwrócenie surowego wskaźnika. Ale nie jestem w 100% pewien, że pamięć obiektów zostanie odpowiednio wyczyszczona. Pobiegłem valgrind
sprawdzić, czy nie ma wycieków pamięci, ale nie znalazłem żadnych. Kto jednak sprząta? 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")
;
}
W 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
Moje pytanie brzmi: czy Rcpp::Xptr<>
jest właściwy sposób zwracania wskaźników, a jeśli tak, to w jaki sposób sprawić, aby R zobaczył wynik jako Double
nie externalptr
? Alternatywnie, jeśli zwrócenie surowego wskaźnika nie powoduje problemów z pamięcią, kto czyści obiekt utworzony przez funkcję?
CustomClass*
. Prawdziwa aplikacja to niestandardowa struktura danych bez odpowiednika R, a wszystkie interakcje odbywają się za pośrednictwem funkcji udostępnionej przez RCPP_MODULE
. Najbliższym dopasowaniem, jakie znalazłem przy wyszukiwaniu motywowanym, był post sprzed 7 lat , w którym wydaje się, że muszę zdefiniować template <> CustomClass* as()
konwerter. Nie jestem jednak pewien, w jaki sposób powinien on wchodzić w interakcje RCPP_MODULE
i RCPP_EXPOSED_CLASS
, zwłaszcza że myślałem, że to drugie zostało już zdefiniowane wrap()
i as()
.
RCPP_EXPOSED_CLASS
i czy RCPP_MODULE
to naprawdę sposób, aby to zrobić? Nigdy wcześniej tego nie używałem ani nie widziałem.
Rcpp::XPtr
utworzyć zewnętrzny wskaźnik z kodu C ++. I chcesz to rzucić,double *
czy cokolwiek innego. Tu powinny być przykłady, w Galerii, na GitHub ... Może dzięki zmotywowanemu wyszukiwaniu możesz znaleźć coś wystarczająco blisko?