r - 在 C++ 中嵌入 R : access elements of a VECSXP

标签 r visual-studio rcpp

所以我从 C++ 调用一些 R 代码,并且为此直接调用 R.dll(我了解 Rcpp,我的 table 上有这本书,但我不能用它来这个具体的事情)。我有一个设置变量的 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 header 中的结构定义手动检查 my_sexp 的内存布局,但我似乎无法正确进行转换以从中获取有意义的值。

那么,有谁可以大致告诉我如何访问列表的元素吗?或者给我举个例子;或者指出 Rcpp 中完成此类转换的位置?我尝试自己找到最后一点,但没有走得太远 - 看起来 Rcpp 的 wrap() 以某种方式“神奇地”(如一般)处理它。

提前致谢。

最佳答案

我没有花太多时间使用 R 的 C 接口(interface),因为我通常坚持使用 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"
*/

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

但是要解决您的问题(尽我所能)-

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

不幸的是,似乎没有那么多关于 R 的 C 内部结构的文档,但 Hadley 有一个有用的 reference page here ,如果其他方法都失败了,您可以深入挖掘 the source itself .

关于r - 在 C++ 中嵌入 R : access elements of a VECSXP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31160607/

相关文章:

R:通过管道输入到函数工厂

visual-studio - 如何增加 Visual Studio C++ 中的内存限制

visual-studio - 尝试将 Cordova 应用程序与商店关联时 Visual Studio 崩溃

c++ - 如何在 R 中进行内联 C++ 函数调用?

c++ - 根据 Rcpp.h 为自定义类扩展 Rcpp::as

r - 一个输出文件可用于多种回归

r - 使用 dplyr 和 mapply 函数时将 R 中的 ggplot2 输出保存到 pdf 文件

r - 找到多边形的视觉中心

c# - 如何在 Visual Studio 中使用正确的编码打开阿拉伯文本文件

c++ - 将 DataFrame 转换为 Matrix 的最有效方法,反之亦然