为多个会话保留 XPtr [英] Keep XPtr for multiple sessions

查看:22
本文介绍了为多个会话保留 XPtr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 R 函数,它创建一个 Primebase Cpp 类,然后返回一个 XPtr 指针.

I have a R function that creates a Primebase Cpp Class and then returns a XPtr<Primebase> pointer.

由于构建过程需要大量时间,我想将 Primebase 的实例保存到我的会话中,以便下次打开 RI 时可以直接访问 Primebase 实例.

As the construction process takes a significant amount of time I'd like to save the instance of Primebase to my session, so that the next time I open up R I can directly access the Primebase instance.

不幸的是,一旦我关闭 R 并且 XPtr 变成一个 空指针,底层对象就会被删除.

Unfortunately the underlying Object gets deleted as soon as I close R and the XPtr turns into a null pointer.

有没有办法阻止 R 删除对象或以任何其他方式保存底层对象?

Is there a way to prevent R from deleting the object or any other way to save the underlying object?

推荐答案

Rcpp::Xptr 管理的 C++ 对象在 R 会话结束时被销毁.如果要保存对象,则必须对其进行序列化.Rcereal 包提供了一种不错的可能性.下面的示例使用一个简单的 Primebase 类在一个构造函数中使用人工睡眠来模拟构造过程中的繁重处理.检查对象的内容后,将其序列化并销毁.之后,对象被反序列化并再次包装到 Xptr 中.请注意,反序列化比构建便宜得多:

The C++ object that is managed by Rcpp::Xptr is destroyed when the R session ends. If you want to save the object, you have to serialize it. One nice possibility is offered by the Rcereal package. The following example uses a trivial Primebase class with an artificial sleep in one constructor to simulate heavy processing during the construction. After checking the object's content, it is serialized and destroyed. Afterwards the object is deserialized and wrapped into an Xptr again. Note that deserialization is much cheaper than construction:

#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

参考文献:

这篇关于为多个会话保留 XPtr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆