Преобразовать Rcpp :: List в C ++ вектор векторов const char * - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь создать интерфейс Rcpp для существующей библиотеки C ++, которая использует const char* для строк. Я думаю, что мне нужно использовать Rcpp :: List для передачи некоторых выходных индексов, которые являются рваным 2D-массивом строк. Но у меня возникают проблемы с преобразованием этого в примитивы C ++, требуемые внешней функцией.

#include <Rcpp.h>

// Enable C++11 via this plugin (Rcpp 0.10.3 or later)
// [[Rcpp::plugins(cpp11)]]

// [[Rcpp::export]]
void test(Rcpp::List IndexList){

      // convert list to this
      const std::vector<std::vector<const char*>> Indexes;
      for (int i = 0; i < IndexList.size(); i++){
          Rcpp::StringVector temp = IndexList[i];
          std::vector<const char*> temp2;
          temp2.clear();
          for (int j = 0; j < temp.size(); j++){
            Rcpp::Rcout << temp[j];
            temp2.push_back(temp[j]);
          }
          Indexes.push_back(temp2);
      }
}

/*** R

test(list(c("a", "b"), c("cde")))

*/

Строка Indexes.push_back(temp2); выдает ошибку, когда я пытаюсь построить этот объект (который мне нужно передать другой функции).

Line 19 passing 'const std::vector<std::vector<const char*> >' as 'this' argument of 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::vector<const char*>; _Alloc = std::allocator<std::vector<const char*> >; std::vector<_Tp, _Alloc>::value_type = std::vector<const char*>]' discards qualifiers [-fpermissive]

Решение

#include <Rcpp.h>

// Enable C++11 via this plugin (Rcpp 0.10.3 or later)
// [[Rcpp::plugins(cpp11)]]

// function that wants this data structure
void feedme(const std::vector<std::vector<const char *>> &Indexes){

    Rcpp::Rcout << " feedme ";
    for (unsigned i = 0; i < Indexes.size(); i++){
        for (unsigned j = 0; j < Indexes[i].size(); j++){
            Rcpp::Rcout << Indexes[i][j];
        }
    }

}

// [[Rcpp::export]]
void test(Rcpp::List IndexList){

      // convert list to this
    Rcpp::Rcout << " test ";
    std::vector<std::vector<const char*>> Indexes;
      for (int i = 0; i < IndexList.size(); i++){
          Rcpp::StringVector temp = IndexList[i];
          std::vector<const char*> temp2;
          temp2.clear();
          for (int j = 0; j < temp.size(); j++){
            Rcpp::Rcout << temp[j];
            temp2.push_back(temp[j]);
          }
          Indexes.push_back(temp2);
      }

      feedme(Indexes);

}


/*** R

test(list(c("a", "b"), c("cde")))

*/

Ответы [ 2 ]

2 голосов
/ 07 ноября 2019

Вы объявляете Indexes как const, но попробуйте изменить его позже:

      const std::vector<std::vector<const char*>> Indexes;
//    ^^^^^
// [...]      
          Indexes.push_back(temp2);

Удалите квалификатор const, чтобы получить скомпилированный код.

2 голосов
/ 07 ноября 2019

Может быть, это поможет. Здесь мы переходим от Rcpp::StringVector до двух векторов как const char *, так и char *. Я почти ожидал, что мне нужно будет использовать const-cast, но он просто построен как есть.

Код
#include <Rcpp.h>

void consumeConstChar(std::vector<const char*> v) {
  for (auto s : v) Rcpp::Rcout << s << std::endl;
}

void consumeChar(std::vector<char*> v) {
  for (auto s : v) Rcpp::Rcout << s << std::endl;
}

// [[Rcpp::export]]
void doStuff(Rcpp::StringVector x) {
  std::vector<const char*> vcc;
  std::vector<char*> vc;
  for (int i=0; i<x.size(); i++) {
    vcc.push_back(x[i]);
    vc.push_back(x[i]);
  }
  consumeConstChar(vcc);
  consumeChar(vc);
}

/*** R
x <- c("The quick", "brown", "fox", "jumped")
doStuff(x)
*/
Демо
R> Rcpp::sourceCpp("~/git/stackoverflow/58741017/answer.cpp")

R> x <- c("The quick", "brown", "fox", "jumped")

R> doStuff(x)
The quick
brown
fox
jumped
The quick
brown
fox
jumped
R> 
...