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

时间:2015-07-01 11:56:46

标签: r visual-studio rcpp

所以我从C ++调用一些R代码,然后我直接调用R.dll(我知道Rcpp,我把书放在桌面上,但我可以&# 39;用它来做这个特定的事情)。我有一个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标题中的结构定义手动检查my_sexp的内存布局,但我似乎无法获得正确的转换以从中获取有意义的值。

那么,是否有人能够大致告诉我如何访问列表的元素;或者指出一个例子;或者指向我在Rcpp的位置进行这样的转换?我试着自己找到最后一点,但没有达到目的 - 似乎Rcpp的wrap()处理它并且神奇地“#”; (以某种方式,一般而言)。

提前致谢。

1 个答案:

答案 0 :(得分:2)

我没有花太多时间在R&C的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的长度,虽然我无法真正说出XLENGTHLENGTHTRUELENGTH之间的差异VECTOR_ELT(lst, i),第一种方法似乎总能产生预期的结果。
  2. 我使用VECSXP访问lst VECTOR_ELT(lst, i)中的第i个元素。
  3. 鉴于数据/功能的上下文,我知道STRSXP正在返回STRSXP - 即字符向量。使用STRING_ELT(..., j)访问此CHARSXP的第j个元素,由于这会返回CHAR,因此我们将其包含在const char*中以获取std::vector<std::string>,这是 var ed = new tinymce.Editor(id, { mode: "specific_textareas", editor_selector: "txt", other_setting: "0" }, tinymce.EditorManager); ed.render(); 添加到<div id="edu-rating"></div> ... <script> $('#edu-rating').on('cocoon:after-insert').raty({ starOn: '<%= image_path('star-on.png') %>', starOff: '<%= image_path('star-off.png') %>', starHalf: '<%= image_path('star-half.png') %>', path: '', scoreName: 'interview_candidate[education]', space: true }); </script>
  4. 不幸的是,似乎 很多R&C的内部文件,但Hadl​​ey有一个有用的reference page here,如果所有其他方法都失败了,你可以挖掘the source itself