Рассмотрим 1) пользовательский класс с потенциально большим объемом памяти и 2) функцию верхнего уровня, которая выполняет некоторую предварительную обработку, а затем создает и возвращает новый объект нашего пользовательского класса. Чтобы избежать ненужного копирования по значению, функция выделяет объект и вместо него возвращает указатель.
Исходя из предыдущего обсуждения , кажется, что правильный способ вернуть указатель на вновь созданный объект - это обернуть его Rcpp::XPtr<>
. Тем не менее, R тогда видит это эффективно externalptr
, и я изо всех сил пытаюсь найти правильный способ придать ему современность RCPP_EXPOSED_CLASS
и RCPP_MODULE
способ делать вещи.
Альтернатива - вернуть необработанный указатель. Но тогда я не уверен на 100%, что память объекта правильно очищена. Я побежал, valgrind
чтобы проверить на утечки памяти, и он не нашел. Однако кто занимается уборкой? Р?
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")
;
}
В 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
Мой вопрос заключается в том, является ли Rcpp::Xptr<>
правильный способ возврата указателей, и если да, то как мне получить R, чтобы увидеть результат как Double
, а не externalptr
? Альтернативно, если возврат необработанного указателя не вызывает проблем с памятью, кто очищает объект, который создает функция?
CustomClass*
. Настоящее приложение представляет собой пользовательскую структуру данных без эквивалента R, и все взаимодействия выполняются с помощью функциональности, предоставляемой RCPP_MODULE
. Самым близким совпадением, найденным в моем поиске, было сообщение 7 лет назад , где, похоже, мне нужно определить template <> CustomClass* as()
конвертер. Однако мне неясно, как оно должно взаимодействовать RCPP_MODULE
и RCPP_EXPOSED_CLASS
, тем более, что я думал, что последнее уже определено wrap()
и as()
.
RCPP_EXPOSED_CLASS
и RCPP_MODULE
действительно ли способ сделать это? Я никогда не использовал и не видел это раньше.
Rcpp::XPtr
создать внешний указатель из кода C ++. И вы хотите, чтобы это было сделано,double *
или какой бы ни была ваша полезная нагрузка. Здесь должны быть примеры, в Галерее, на GitHub ... Может быть, с мотивированным поиском вы можете найти что-то достаточно близкое?