Considere 1) uma classe personalizada com uma impressão de memória potencialmente grande e 2) uma função de nível superior que realiza algum pré-processamento, depois cria e retorna um novo objeto de nossa classe personalizada. Para evitar cópias desnecessárias por valor, a função aloca o objeto e retorna um ponteiro para ele.
Com base em uma discussão anterior , parece que a maneira correta de retornar um ponteiro para um objeto recém-criado é envolvê-lo Rcpp::XPtr<>
. No entanto, R o vê efetivamente como externalptr
, e estou lutando para encontrar a maneira correta de interpretá-la com a maneira moderna RCPP_EXPOSED_CLASS
e RCPP_MODULE
de fazer as coisas.
A alternativa é retornar o ponteiro bruto. Mas não tenho 100% de certeza de que a memória do objeto seja devidamente limpa. Corri valgrind
para testar vazamentos de memória e não encontrei nenhum. No entanto, quem faz a limpeza? 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")
;
}
Em 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
Minha pergunta é se Rcpp::Xptr<>
é a maneira correta de retornar ponteiros e, se sim, como faço para que R veja o resultado como Double
não externalptr
? Como alternativa, se o retorno de um ponteiro bruto não causa problemas de memória, quem limpa o objeto que a função cria?
CustomClass*
. O aplicativo real é uma estrutura de dados customizada sem equivalente em R e todas as interações são feitas através da funcionalidade exposta pelo RCPP_MODULE
. A correspondência mais próxima que minha pesquisa motivada encontrou foi uma postagem de 7 anos atrás , onde parece que eu preciso definir um template <> CustomClass* as()
conversor. No entanto, não estou claro como ele deve interagir RCPP_MODULE
e RCPP_EXPOSED_CLASS
, principalmente porque pensei que o último já definiu wrap()
e as()
.
RCPP_EXPOSED_CLASS
e RCPP_MODULE
é realmente a maneira de fazê-lo? Eu nunca usei ou vi isso antes.
Rcpp::XPtr
criar um ponteiro externo a partir do código C ++. E você deseja transmiti-lodouble *
ou seja qual for sua carga útil. Deve haver exemplos aqui, na Galeria, no GitHub ... Talvez com uma pesquisa motivada você possa encontrar algo próximo o suficiente?