在 C++ 中嵌入 R:访问 VECSXP 的元素

Embedding R in C++: access elements of a VECSXP

所以我从 C++ 调用了一些 R 代码,为此我直接调用了 R.dll(我知道 Rcpp,我桌上有这本书,但我可以'不要将它用于这个特定的东西)。我有一个设置变量的 R 脚本,我想访问该变量的内容。

变量是字符串列表;在 C++ 中,当我执行 TYPEOF(my_sexp) 时,我得到 VECSXP;到目前为止,一切都很好。现在我想将该列表的内容读入 std::vector。我尝试了以下想法的许多排列:

SEXP vector_exp = VECTOR_ELT(my_sexp, 0);
int element_count = TRUELENGTH(vector_exp);
for (int i = 0 ; i < element_count ; i++) {
    SEXP elem_sexp = VECTOR_ELT(my_sexp, i);
    std::string element_string = R_CHAR(elem_sexp);
}

我的问题: - 使用 TRUELENGTH,我可以访问冲突。使用 LENGTH,我得到了一个错误的值。 - 使用 VECTOR_ELT() 访问列表元素会导致访问冲突。 - 我已经尝试根据 R headers 中的结构定义手动检查 my_sexp 的内存布局,但我似乎无法正确地进行转换以从中获取有意义的值。

所以,有没有人能大致告诉我如何访问列表的元素;或者给我举个例子;或指向 Rcpp 中完成此类转换的位置?我试着自己找到最后一点,但没走多远——Rcpp 的 wrap() 似乎以某种方式处理了它 'magically'(一般来说)。

提前致谢。

我没有花太多时间使用 R 的 C 接口,因为我通常坚持使用 Rcpp,但以下似乎有效:

#include <Rcpp.h>

// [[Rcpp::export]]
void print_list_as_vector(SEXP lst) {
  PROTECT(lst);
  R_xlen_t n_list = XLENGTH(lst);
  R_xlen_t n_elem = 0;

  for (R_xlen_t i = 0; i < n_list; i++) {
    n_elem += XLENGTH(VECTOR_ELT(lst, i));
  }

  std::vector<std::string> vs;
  vs.reserve(n_elem);
  for (R_xlen_t i = 0; i < n_list; i++) {
    R_xlen_t nj = XLENGTH(VECTOR_ELT(lst, i));
    for (R_xlen_t j = 0; j < nj; j++) {
      vs.push_back(CHAR(STRING_ELT(VECTOR_ELT(lst, i), j)));
    }
  }

  for (std::size_t i = 0; i < vs.size(); i++) {
    Rcpp::Rcout <<
      vs[i] << std::endl;
  }

  UNPROTECT(1);
}

/*** R

clist <- list(c("a", "b", "c"), c("l", "m", "n", "o", "p"), c("xyz1", "xyz2"))

print_list_as_vector(clist)
#a
#b
#c
#l
#m
#n
#o
#p
#xyz1
#xyz2

unlist(clist)
# [1] "a"    "b"    "c"    "l"    "m"    "n"    "o"    "p"    "xyz1" "xyz2"
*/

如您所见,这是在 R 中测试的/使用 Rcpp 属性,但在实际的代码中,我试图坚持使用 C 接口来复制您的情况。

但为了解决您的问题(尽我所能)-

  1. 我一直使用XLENGTH来获取SEXP的长度,虽然我不能真正说出XLENGTHLENGTHLENGTH之间的区别TRUELENGTH,第一种方法似乎总能产生预期的结果。
  2. 我正在使用 VECTOR_ELT(lst, i) 访问 VECSXP lst 中的第 i 个元素。
  3. 鉴于数据/函数的上下文,我知道 VECTOR_ELT(lst, i) 正在返回一个 STRSXP - 即一个字符向量。这个STRSXP的第j个元素是用STRING_ELT(..., j)访问的,由于这个returns一个CHARSXP,我们把它包在CHAR中得到一个const char*,它被添加到 std::vector<std::string>

不幸的是,似乎没有 很多关于 R 的 C 内部结构的文档,但是 Hadley 有一个有用的 reference page here, and if all else fails, you can dig through the source itself.