将 SEXP 函数 args 放入 Rcpp::Xptr 时是否应该受到保护? [英] Should SEXP function args be PROTECTed when put inside an Rcpp::Xptr?
问题描述
看看下面的(过度简化的)Rcpp
+ R
代码:
Look at the (oversimplified) Rcpp
+ R
code below :
test.cpp:
#include <Rcpp.h>
using namespace Rcpp;
class VecWrap{
public:
SEXP vector;
int type;
VecWrap(SEXP vector)
{
this->vector = vector;
this->type = TYPEOF(vector);
if(this->type != INTSXP && this->type != REALSXP)
stop("invalid type");
}
bool contains(double val){
if(type == INTSXP){
IntegerVector v = vector;
for(int i = 0; i < v.size(); i++)
if(v[i] == val)
return true;
}else if(type == REALSXP){
NumericVector v = vector;
for(int i = 0; i < v.size(); i++)
if(v[i] == val)
return true;
}
return false;
}
};
// [[Rcpp::export]]
SEXP createVecWrap(SEXP x) {
VecWrap* w = new VecWrap(x);
return XPtr< VecWrap >(w);
}
// [[Rcpp::export]]
SEXP vecWrapContains(XPtr< VecWrap > w, double val){
return wrap(w->contains(val));
}
test.R:
library(Rcpp)
sourceCpp(file='test.cpp')
v <- 1:10e7
w <- createVecWrap(v)
vecWrapContains(w, 10000) # it works
# remove v and call the garbage collector
rm(v)
gc()
vecWrapContains(w, 10000) # R crashes (but it works with small vector "v")
基本上,我将作为 createVecWrap
函数参数接收的 SEXP
向量放入自定义类 VecWrap
中,以便稍后使用.
Basically I put inside the custom class VecWrap
the SEXP
vector received as argument of createVecWrap
function, in order to use it later.
但是,正如代码中的注释所解释的那样,如果我从 R 端删除向量 v
并调用垃圾收集器,则当我尝试访问该向量时,R 进程会崩溃.
该载体是否应该以某种方式受到 GC 的保护?如果是这样,如何?(如果可能的话,Rcpp 风格)
But, as explained by the comments in the code, if I remove the vector v
from the R-side and call the garbage collector, the R process crashes when I try to access the vector.
Should the vector be protected by the GC in someway ? If so, how? (Rcpp-style if possible)
推荐答案
一般来说你应该尽量坚持 C++ 类型系统/Rcpp 类(re:避免直接处理 SEXP
如果可能的话).但是,Rcppcode> 类
将为您的 SEXP
提供垃圾收集器的保护,并且在这种情况下似乎有效:
Generally speaking you should try to stick to the C++ type system / Rcpp classes as much as possible (re: avoid handling SEXP
directly if possible). However, the RObject
class will provide your SEXP
with protection from the garbage collector, and seems to work in this case:
#include <Rcpp.h>
class VecWrap {
public:
Rcpp::RObject vector;
int type;
VecWrap(SEXP vector_)
: vector(vector_)
{
type = vector.sexp_type();
if (type != INTSXP && type != REALSXP) {
Rcpp::stop("invalid type");
}
}
bool contains(double val) {
if (type == INTSXP){
Rcpp::IntegerVector v = Rcpp::as<Rcpp::IntegerVector>(vector);
for (int i = 0; i < v.size(); i++) {
if (v[i] == val) return true;
}
} else if (type == REALSXP) {
Rcpp::NumericVector v = Rcpp::as<Rcpp::NumericVector>(vector);
for (int i = 0; i < v.size(); i++) {
if (v[i] == val) return true;
}
}
return false;
}
};
// [[Rcpp::export]]
Rcpp::XPtr<VecWrap> createVecWrap(SEXP x) {
return Rcpp::XPtr<VecWrap>(new VecWrap(x));
}
// [[Rcpp::export]]
bool vecWrapContains(Rcpp::XPtr<VecWrap> w, double val) {
return w->contains(val);
}
<小时>
v <- 1:10e7
w <- createVecWrap(v)
vecWrapContains(w, 10000)
# [1] TRUE
rm(v)
gc()
# used (Mb) gc trigger (Mb) max used (Mb)
# Ncells 366583 19.6 750400 40.1 460000 24.6
# Vcells 100559876 767.3 145208685 1107.9 100560540 767.3
vecWrapContains(w, 10000)
# [1] TRUE
<小时>
无关:考虑使用 { }
作为你的控制流结构,不要被 this->
带走;这两者都会提高 IMO 代码的可读性.
Unrelated: consider using { }
for your control flow structures, and don't get carried away with this->
; both of those will improve the readability of your code IMO.
这篇关于将 SEXP 函数 args 放入 Rcpp::Xptr 时是否应该受到保护?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!