Лучший способ получить доступ к членам класса C ++ из R с помощью Rcpp - PullRequest
0 голосов
/ 29 января 2019

У меня есть имитационная модель, написанная как класс C ++.Я написал простую оболочку Rcpp, которая позволяет запускать ее из R.Я задаюсь вопросом о том, как наилучшим образом получить и установить свойства модели (двойники, векторы двойников и векторы векторов двойников) из R.Я использую три std::unordered_map как способ предоставления пользователю доступа к свойствам модели:

class molly_class {

  ...

  public:

  // unordered_map gives user efficient access to variables by name
  std::unordered_map< std::string , double > variable;
  std::unordered_map< std::string , std::vector< double >* > vector; // pointers to vectors
  std::unordered_map< std::string , std::vector< std::vector< double > >* > array; // pointers to arrays

  ...

}

В моей оболочке Rcpp я предоставил методы для доступа к "переменным" (скалярам) "векторы "и" массивы "из R.Это работает, но я не уверен, что это правильный путь.Я хочу избежать ненужного копирования информации, и, возможно, есть более эффективные / более безопасные способы передачи данных назад и вперед?Я заглянул в документацию Rcpp о разоблачении классов C ++ и RCCP_MODULE, но на самом деле я этого не понимаю.Заранее спасибо.Оболочка Rcpp содержит следующее:

molly_class molly;

// return molly scalar variables and their values as a named vector
// [[Rcpp::export]]
Rcpp::NumericVector get_molly_variables(){
    Rcpp::NumericVector var_vector;
    molly.pull_variables_from_model();
    var_vector = molly.variable; // coerces unordered_map to named vector
    return var_vector;
}

// set values of molly variables from the supplied named vector
// [[Rcpp::export]]
void set_molly_variables(Rcpp::NumericVector var_vector){
    Rcpp::CharacterVector names = var_vector.names(); // types are a bit tricky
    std::string name_i;
    molly.pull_variables_from_model();
    for (int i=0; i<var_vector.size(); ++i){
        name_i = Rcpp::as<std::string>(names[i]); // types are a bit tricky
        if (molly.variable.find(name_i) != molly.variable.end()){
            molly.variable[name_i] = var_vector[i];
        } else {
            Rcpp::Rcout << "molly error : unknown variable " << name_i << std::endl;
        }
    }
    molly.push_variables_to_model();
}

// return names of molly vectors
// [[Rcpp::export]]
Rcpp::StringVector get_molly_vectors(){
    Rcpp::StringVector key_vector;
    // /7699214/poluchenie-spiska-klychei-i-znachenii-iz-unorderedmap
    for (auto mvi : molly.vector){
        key_vector.push_back(mvi.first);
    }
    return key_vector;
}

// return a molly vector 
// [[Rcpp::export]]
Rcpp::NumericVector get_molly_vector(Rcpp::String vec_name){
    Rcpp::NumericVector vec_values;
    vec_values = *molly.vector[vec_name];
    return vec_values;
}

// set a molly vector using the supplied vector
// [[Rcpp::export]]
void set_molly_vector(Rcpp::String vec_name, Rcpp::NumericVector vec_values){
    int ncols = (*molly.vector[vec_name]).size();
    if (vec_values.size() == ncols){
        for (int col=0; col<ncols; col++){
            (*molly.vector[vec_name]).at(col) = vec_values.at(col);
        }
    } else {
        Rcpp::Rcout << "molly error : supplied vector does not match length of " << vec_name << std::endl;
    }
}

// return names of molly arrays
// [[Rcpp::export]]
Rcpp::StringVector get_molly_arrays(){
    Rcpp::StringVector key_vector;
    // /7699214/poluchenie-spiska-klychei-i-znachenii-iz-unorderedmap
    // key_vector.reserve(molly.vector.size());
    for (auto mvi : molly.array){
        key_vector.push_back(mvi.first);
    }
    return key_vector;
}

// return a molly array as a matrix
// [[Rcpp::export]]
Rcpp::NumericMatrix get_molly_array(Rcpp::String arr_name){
    int nrows = (*molly.array[arr_name]).size();
    int ncols = (*molly.array[arr_name]).at(0).size();
    Rcpp::NumericMatrix arr_values(nrows, ncols);
    for (int row=0; row<nrows; row++){
        for (int col=0; col<ncols; col++){
            arr_values(row, col) =  (*molly.array[arr_name]).at(row).at(col);
        }
    }
    return arr_values;
}

// set a molly array using the supplied matrix
// [[Rcpp::export]]
void set_molly_array(Rcpp::String arr_name, Rcpp::NumericMatrix arr_values){
    int nrows = (*molly.array[arr_name]).size();
    int ncols = (*molly.array[arr_name]).at(0).size();
    if (arr_values.nrow() == nrows && arr_values.ncol() == ncols){
        for (int row=0; row<nrows; row++){
            for (int col=0; col<ncols; col++){
                (*molly.array[arr_name]).at(row).at(col) = arr_values(row, col);
            }
        }
    } else {
        Rcpp::Rcout << "molly error : supplied matrix does not match dimensions of " << arr_name << std::endl;
    }

Обратите внимание, что pull_variables_from_model() заполняет unordered_map variable, а push_variables_to_model() использует unordered_map variable для установки внутренних переменных модели,которые являются частными членами molly_class.unordered_map variable используется только как интерфейс, позволяющий пользователям получать доступ к внутренним переменным модели по имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...