我做了一个可重现的小例子:
#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(我认为是最新的)。
这似乎与临时对象有关——当你的第二个函数运行时,第一个函数的“内容”已经消失了。
所以要么就做
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)