Rcpp: как использовать защиту от разматывания?

#rcpp

#rcpp

Вопрос:

Мне было интересно, как я мог бы заставить некоторый код Rcpp использовать автоматическую защиту от разматывания во всех объектах Rcpp.

Например, предположим, что у меня есть такой код:

 #include <stdint.h>
#include <Rcpp.h>

class MyObj {
public:
    int val;
    MyObj(int val) : val(val) {};
    ~MyObj() {
        std::cout << "I' being destructed - value was: " << val << std::endl;
    }
};

// [[Rcpp::export]]
Rcpp::NumericVector crashme(unsigned int seed)
{
    srand(seed);
    MyObj obj1(rand());
    Rcpp::NumericVector out(INT64_MAX-1, 100.);
    return out;
}
 

Когда я вызываю crashme , obj1 не уничтожается до завершения функции из-за длинных переходов R, от которых я хочу защитить.

Я вижу, что есть функция Rcpp::unwindProtect , но она реализована как нечто, требующее обратного вызова.

Я не уверен на 100%, правильно ли я все делаю, но мне удалось добавить защиту от разматывания следующим образом:

 #include <stdint.h>
#include <Rcpp.h>
#include <Rcpp/unwindProtect.h>
// [[Rcpp::plugins(unwindProtect)]]

class MyObj {
public:
    int val;
    MyObj(int val) : val(val) {};
    ~MyObj() {
        std::cout << "I' being destructed - value was: " << val << std::endl;
    }
};

struct NumVecArgs {
    size_t size;
    double fillwith;
};

SEXP alloc_NumVec(void *data)
{
    NumVecArgs *args = (NumVecArgs*)data;
    return Rcpp::NumericVector(args->size, args->fillwith);
}

// [[Rcpp::export]]
Rcpp::NumericVector crashme(unsigned int seed)
{
    srand(seed);
    MyObj obj1(rand());
    NumVecArgs args = {INT64_MAX-1, 100.};
    Rcpp::NumericVector out = Rcpp::unwindProtect(alloc_NumVec, (void*)amp;args);
    return out;
}
 

Теперь вызов crashme будет успешно уничтожен obj1 и выведет сообщение деструктора.

Но это очень неудобно, поскольку у меня есть ряд различных распределений объектов Rcpp, использующих разные типы конструкторов, что подразумевает либо определение другой структуры и обратного вызова для каждого из них, либо перевод всех вызовов в длинные лямбда-функции.

Есть ли какой-либо способ автоматически выполнять все вызовы конструкторов, например Rcpp::NumericVector , и Rcpp::IntegerVector иметь защиту от разматывания?