使用外部指针进行奇怪的访问

F. *_*ivé 2 r rcpp

我做了一个可重现的小例子:

#include <Rcpp.h>
using namespace Rcpp;

class Index {
public:
  Index(int i_) : i(i_) {}
  int getI() { return i; }
private:
  int i;
};

// [[Rcpp::export]]
SEXP getXPtrIndex(int i) {
  Rcout << "getXPtrIndex: i = " << i << std::endl;
  Index ind(i);
  Rcout << "getXPtrIndex: ind.i = " << ind.getI() << std::endl;
  return XPtr<Index>(&ind, true);
}

// [[Rcpp::export]]
void getXPtrIndexValue(SEXP ptr) {
  XPtr<Index> ind_ptr(ptr);
  Rcout << "getXPtrIndexValue: ind_ptr->i = " << ind_ptr->getI() << std::endl;
  Index ind = *ind_ptr;
  Rcout << "getXPtrIndexValue: ind.i = " << ind.getI() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

基本上,我定义了一个小类,以及一个用于获取此类元素的外部指针的函数。最后一个函数用于在将类元素返回到 C++ 时打印奇怪的访问器。

R 结果:

> (extptr <- getXPtrIndex(10))
getXPtrIndex: i = 10
getXPtrIndex: ind.i = 10
<pointer: 0x7ffeeec31b00>

> getXPtrIndexValue(extptr)
getXPtrIndexValue: ind_ptr->i = 33696400
getXPtrIndexValue: ind.i = 0
Run Code Online (Sandbox Code Playgroud)

为什么我无法访问10

我正在使用Rcpp版本 0.12.12(我认为是最新的)。

Dir*_*tel 5

这似乎与临时对象有关——当你的第二个函数运行时,第一个函数的“内容”已经消失了。

所以要么就做

Index ind(10);
Run Code Online (Sandbox Code Playgroud)

全局的,并注释掉第一个函数中的行。然后一切都很顺利(我稍微改变了 R 调用):

R> extptr <- getXPtrIndex(10)
getXPtrIndex: i = 10
getXPtrIndex: ind.i = 10

R> getXPtrIndexValue(extptr)
getXPtrIndexValue: ind_ptr->i = 10
getXPtrIndexValue: ind.i = 10
R> 
Run Code Online (Sandbox Code Playgroud)

或者当你让你Index反对static以确保持久性时,它也会以同样的方式起作用。下面更正了示例。

#include <Rcpp.h>
using namespace Rcpp;

class Index {
public:
  Index(int i_) : i(i_) {}
  int getI() { return i; }
private:
  int i;
};

// [[Rcpp::export]]
SEXP getXPtrIndex(int i) {
  Rcout << "getXPtrIndex: i = " << i << std::endl;
  static Index ind(i);
  Rcout << "getXPtrIndex: ind.i = " << ind.getI() << std::endl;
  return XPtr<Index>(&ind, true);
}

// [[Rcpp::export]]
void getXPtrIndexValue(SEXP ptr) {
  XPtr<Index> ind_ptr(ptr);
  Rcout << "getXPtrIndexValue: ind_ptr->i = " << ind_ptr->getI() << std::endl;
  Index ind = *ind_ptr;
  Rcout << "getXPtrIndexValue: ind.i = " << ind.getI() << std::endl;
}

/*** R
extptr <- getXPtrIndex(10)
getXPtrIndexValue(extptr)
*/
Run Code Online (Sandbox Code Playgroud)