I'm trying to expose a simple Student class in C++ to R using Rcpp within a package. Here's my setup...
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)
After calling devtools::document()
, I get the following NAMESPACE file
# Generated by roxygen2: do not edit by hand
export(simulate_student)
importFrom(Rcpp,sourceCpp)
useDynLib(student, .registration = TRUE)
Now, after doing clean and rebuild from RStudio (i.e. R CMD INSTALL --preclean --no-multiarch --with-keep.source student
) the package compiles and loads without issue. If I run the simulate_student()
function, I get the expected result. However, when I try to make a new Student object with stud <- new(Student)
I get Error in .getClassesFromCache(Class) : object 'Student' not found
This issue seems similar to this SO post but the accepted answer does not seem to solve my issue. Furthermore, I've looked into the Annoy source code mentioned by Dirk, but I don't see any helpful differences between that code and mine except for the RCPP_EXPOSED_CLASS_NODECL(AnnoyEuclidean)
snippets which I've tried placing in my code but also do not help.
unif_module <- Module( "unif_module", getDynLib(fx_unif ) )
statement to define the module in R land. – MrFlick