Держите XPtr для нескольких сессий - PullRequest
0 голосов
/ 03 ноября 2018

У меня есть функция R, которая создает Primebase класс Cpp и затем возвращает указатель XPtr<Primebase>.

Поскольку процесс построения занимает значительное количество времени, я бы хотел сохранить экземпляр Primebase в моем сеансе, чтобы в следующий раз, когда я открою R, я мог получить прямой доступ к экземпляру Primebase.

К сожалению, базовый объект удаляется, как только я закрываю R, и XPtr превращается в null pointer.

Есть ли способ предотвратить удаление объекта R или любой другой способ сохранить базовый объект?

1 Ответ

0 голосов
/ 05 ноября 2018

Объект C ++, которым управляет Rcpp::Xptr, уничтожается, когда заканчивается сеанс R. Если вы хотите сохранить объект, вы должны его сериализовать. Одна хорошая возможность предоставляется пакетом Rcereal . В следующем примере используется тривиальный класс Primebase с искусственным сном в одном конструкторе для имитации тяжелой обработки во время построения. После проверки содержимого объекта он сериализуется и уничтожается. После этого объект десериализуется и снова помещается в Xptr. Обратите внимание, что десериализация намного дешевле, чем строительство:

#include <Rcpp.h>
// [[Rcpp::plugins("cpp11")]]
// [[Rcpp::depends(Rcereal)]]
#include <cereal/archives/binary.hpp>
#include <chrono>
#include <fstream>
#include <thread>

class Primebase
{
private:
  int x;

public:
  Primebase() : x{0} {};
  Primebase(int x_) : x{x_} {std::this_thread::sleep_for(std::chrono::seconds(1));};

  int answer() {return x;}

  template <class Archive>
  void serialize(Archive & ar)
  {
    ar(x);
  }
};

// [[Rcpp::export]]
Rcpp::XPtr<Primebase> create(int x) {
  Primebase* instance = new Primebase(x);
  return Rcpp::XPtr<Primebase>(instance);
}


// [[Rcpp::export]]
int answer(Rcpp::XPtr<Primebase> xptr) {
  return xptr.get()->answer();
}

// [[Rcpp::export]]
void mySerialize(Rcpp::XPtr<Primebase> xptr, std::string filename) {
  std::ofstream os(filename, std::ios::binary);
  cereal::BinaryOutputArchive archive(os);
  archive(*xptr.get());
}

// [[Rcpp::export]]
Rcpp::XPtr<Primebase> myDeserialize(std::string filename) {
  std::ifstream is(filename, std::ios::binary);
  cereal::BinaryInputArchive archive(is);
  Primebase* instance = new Primebase;
  archive(*instance);
  return Rcpp::XPtr<Primebase>(instance);
}


/*** R
system.time(xptr <- create(42))
answer(xptr)
mySerialize(xptr, "test.cereal")
rm(xptr)
exists("xptr")
system.time(xptr <-myDeserialize("test.cereal")) 
answer(xptr)
*/

Выход:

> system.time(xptr <- create(42))
   user  system elapsed 
  0.000   0.000   1.001 

> answer(xptr)
[1] 42

> mySerialize(xptr, "test.cereal")

> rm(xptr)

> exists("xptr")
[1] FALSE

> system.time(xptr <-myDeserialize("test.cereal")) 
   user  system elapsed 
      0       0       0 

> answer(xptr)
[1] 42

Ссылки:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...