Предоставьте простой класс C ++ Student для R с использованием модулей Rcpp - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь представить простой класс Student в C ++ для R, используя Rcpp в пакете.Вот мои настройки ...

src /

Student.hpp
//  Student.hpp

#ifndef Student_hpp
#define Student_hpp

#include <string>
#include <vector>

class Student
{
public:

    // Constructor
    Student(std::string name, int age, bool male);

    // Getters
    std::string GetName();
    int GetAge();
    bool IsMale();
    std::vector<int> GetFavoriteNumbers();

    // Methods
    bool LikesBlue();

private:

    // Member variables
    std::string name;
    int age;
    bool male;
    std::vector<int> favoriteNumbers;
};

#endif /* Student_hpp */
Student.cpp
//  Student.cpp

#include "Student.hpp"

// Constructor
Student::Student(std::string name, int age, bool male) {
  this->name = name;
  this->age = age;
  this->male = male;
  this->favoriteNumbers = {2, 3, 5, 7, 11};
}

// Getters
bool Student::IsMale() { return male; }
int Student::GetAge() { return age; }
std::string Student::GetName() { return name; }
std::vector<int> Student::GetFavoriteNumbers() { return favoriteNumbers; }

// Methods
bool Student::LikesBlue() {
    return (male || age >= 10);
}
glue.cpp
// glue.cpp
// To use c++11, first run: Sys.setenv("PKG_CXXFLAGS"="-std=c++11")  ...or use a Makevars file

#include <Rcpp.h>
#include "Student.hpp"
using namespace Rcpp;

//' Simulate a student
//'
//' @export
// [[Rcpp::export]]
std::vector<int> simulate_student() {
  Student s = Student("bob", 10, true);
  return s.GetFavoriteNumbers();
}

// Expose (some of) the Student class
RCPP_MODULE(Student){
  class_<Student>("Student")
  .constructor<std::string,int,bool>()
  .method("LikesBlue", &Student::LikesBlue)
  ;
}

R /

student.R
#' student
#'
#' A cool package
#'
#' Imports
#' @useDynLib student, .registration = TRUE
#' @importFrom Rcpp sourceCpp
"_PACKAGE"

Rcpp::loadModule(module = "Student", TRUE)

После вызова devtools::document() я получаю следующий файл NAMESPACE

NAMESPACE
# Generated by roxygen2: do not edit by hand

export(simulate_student)
importFrom(Rcpp,sourceCpp)
useDynLib(student, .registration = TRUE)

Теперь, после выполнения очистки и перестройки из RStudio (т.е. R CMD INSTALL --preclean --no-multiarch --with-keep.source student), пакет компилируется и загружается без проблем.Если я запускаю функцию simulate_student(), я получаю ожидаемый результат.Однако, когда я пытаюсь создать новый объект Student с stud <- new(Student), я получаю Ошибка в .getClassesFromCache (Class): объект 'Student' не найден

Эта проблема похожа на этот пост но принятый ответ, похоже, не решает мою проблемуКроме того, я изучил исходный код Annoy , упомянутый Дирком, но я не вижу каких-либо полезных отличий между этим кодом и моим, за исключением фрагментов RCPP_EXPOSED_CLASS_NODECL(AnnoyEuclidean), которые я пытался поместить в свой код.код, но также не помогают.

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Глядя на два пакета, основное различие связано с настройкой импорта и экспорта функций.

В частности, оба пакета methods и Rcpp отсутствуют как fullимпортирует в файл NAMESPACE.Кроме того, вместо индивидуального экспорта каждой функции используется глобальный шаблон экспорта.

RcppAnnoy

useDynLib(RcppAnnoy, .registration=TRUE)
import(methods, Rcpp)
exportPattern("^[[:alpha:]]+")          # export all identifiers starting with letters

https://github.com/eddelbuettel/rcppannoy/blob/1ce871ae52730098ddc7355597613e8313e23ac9/NAMESPACE#L1-L3

RcppStudent

roxygen2:

#' @useDynLib RcppStudent, .registration = TRUE
#' @import methods Rcpp
#' @exportPattern "^[[:alpha:]]+"

NAMESPACE:

# Generated by roxygen2: do not edit by hand

exportPattern("^[[:alpha:]]+")
import(Rcpp)
import(methods)
useDynLib(RcppStudent, .registration = TRUE)

https://github.com/r-pkg-examples/rcpp-modules/blob/ca5d13ddd391d9fd4ffb50b4306131d2839f8af5/NAMESPACE#L5-L7

0 голосов
/ 07 декабря 2018

Ответ и комментарии к этой ТАКОЙ записи помогли мне.Кажется, мне нужно было

1) изменить @importFrom Rcpp sourceCpp на @import Rcpp и
2) Добавить export(Student) в мой файл NAMESPACE (хотя я ищу, как сделать это красиво с roxygen2 вместовставив это вручную)

После вышеуказанных изменений я могу запустить

> stud <- new(Student, name = "Ben", age = 26, male = T)
> stud$LikesBlue()
[1] TRUE

ОБНОВЛЕНИЕ
Кажется, я могу добавить #' @export Student к student.R для roxygenдля автоматического добавления бита export(Student) в NAMESPACE, поэтому мне не нужно изменять NAMESPACE вручную.

UPDATE2
Я задокументировал свои действия в этом сообщении в блоге

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