Как установить атрибут класса элемента Rcpp :: List? - PullRequest
3 голосов
/ 10 октября 2019

В исходном файле C ++ ниже, в функции glfw_get_monitors как установить атрибут класса каждого элемента объекта monitor_ptrs?

Строка monitor_ptrs[i].attr("class") = "GLFWmonitor"; выдает ошибку компиляции:

‘Rcpp::Vector<19>::Proxy’ {aka ‘class Rcpp::internal::generic_proxy<19>’} has no member named ‘attr’

glfw_types.h

#ifndef RCPP_GLFW_TYPES_H
#define RCPP_GLFW_TYPES_H

#include <Rcpp.h>
#include <GLFW/glfw3.h>

void glfw_destroy_monitor(GLFWmonitor*);

// https://stackoverflow.com/questions/41210595/s4-object-with-a-pointer-to-a-c-struct

typedef Rcpp::XPtr<GLFWwindow, Rcpp::PreserveStorage, glfwDestroyWindow> GLFWwindow_ptr;
typedef Rcpp::XPtr<GLFWmonitor, Rcpp::PreserveStorage, glfw_destroy_monitor> GLFWmonitor_ptr;


#endif

Исходный файл C ++

#include "glfw_types.h"
using namespace Rcpp;

// [[Rcpp::export]]
GLFWmonitor_ptr glfw_get_primary_monitor() {

  GLFWmonitor_ptr new_monitor = GLFWmonitor_ptr(glfwGetPrimaryMonitor(), true);

  new_monitor.attr("class") = "GLFWmonitor";

  return new_monitor;
}

// [[Rcpp::export]]
Rcpp::List glfw_get_monitors() {

  int nr_monitors;
  GLFWmonitor** monitors = glfwGetMonitors(&nr_monitors);
  Rcpp::List monitor_ptrs(nr_monitors);

  for(int i = 0; i < nr_monitors; i++) {
    monitor_ptrs[i] = GLFWmonitor_ptr((GLFWmonitor*)monitors[i], true);
    monitor_ptrs[i].attr("class") = "GLFWmonitor";
  }

  return monitor_ptrs;
}

1 Ответ

3 голосов
/ 10 октября 2019

Проблема здесь , когда вы пытаетесь назначить класс. Рассмотрим следующий более минимальный пример:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::List foo() {
    // Setup the list
    Rcpp::List result(1);
    // Setup the object that will go in the list
    Rcpp::IntegerVector x = Rcpp::seq(1, 10);
    // Your approach was to add it to the list, THEN set the class attribute
    result[0] = x;
    result[0].attr("class") = "bar";
    return result;
}

enter image description here

Вы не можете напрямую добавить класс в синтаксис доступа к элементу, подобный этому. Однако вы можете классифицировать объект, а затем добавить его в список:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::List foo() {
    // Setup the list
    Rcpp::List result(1);
    // Setup the object that will go in the list
    Rcpp::IntegerVector x = Rcpp::seq(1, 10);
    // Your approach was to add it to the list, THEN set the class attribute
    // result[0] = x;
    // result[0].attr("class") = "bar";
    // What we need to do is set the class of that object
    x.attr("class") = "bar";
    // BEFORE adding it to the list
    result[0] = x;
    return result;
}

/*** R
foo()
*/
foo()
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10
attr(,"class")
[1] "bar"

Обновление

Обратите внимание, что это проблема во многих других контекстах с Rcpp::List sтакже. Рассмотрим следующее:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::List baz() {
    Rcpp::List result(1);
    Rcpp::IntegerVector x = Rcpp::seq(1, 10);
    result[0] = x;
    Rcpp::Rcout << result[0][1] << std::endl;
    result[0][2] += 1;
    return result;
}

enter image description here

Сравните это с использованием std::vector из Rcpp::IntegerVector с:

#include <Rcpp.h>

// [[Rcpp::export]]
void qux() {
    std::vector<Rcpp::IntegerVector> result(1);
    Rcpp::IntegerVector x = Rcpp::seq(1, 10);
    result[0] = x;
    Rcpp::Rcout << result[0][0] << std::endl;
    result[0][2] += 1;
    Rcpp::Rcout << result[0] << std::endl;
}
qux()
1
1 2 4 4 5 6 7 8 9 10

Как обсуждалось в нескольких местах (постарайтесь вернуться позже и добавить несколько ссылок), вам обычно нужно быть более явным, когда речь идет о Rcpp::List, потому что его элементы могут быть почти чем угодно .

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