我正尝试在包中使用Rcpp向R公开C ++中的简单Student类。这是我的设置...
// 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)
;
}
#' student
#'
#' A cool package
#'
#' Imports
#' @useDynLib student, .registration = TRUE
#' @importFrom Rcpp sourceCpp
"_PACKAGE"
Rcpp::loadModule(module = "Student", TRUE)
调用devtools::document()
后,我得到以下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
)执行 clean and rebuild 之后,程序包便可以编译和加载了。如果运行simulate_student()
函数,我将得到预期的结果。但是,当我尝试使用stud <- new(Student)
创建新的Student对象时,在.getClassesFromCache(Class)中出现错误:找不到对象'Student'
此问题似乎与this SO post类似,但是接受的答案似乎无法解决我的问题。此外,我研究了Dirk提到的Annoy source code,但是除了我尝试将RCPP_EXPOSED_CLASS_NODECL(AnnoyEuclidean)
片段插入了代码外,我没有看到该代码与我的代码之间有任何有益的区别。也无济于事。
答案 0 :(得分:3)
浏览两个软件包,主要区别在于如何设置功能的导入和导出。
特别是,methods
文件中的{strong>完全导入都缺少Rcpp
和NAMESPACE
软件包。另外,不是单独导出每个函数,而是使用全局导出模式。
useDynLib(RcppAnnoy, .registration=TRUE)
import(methods, Rcpp)
exportPattern("^[[:alpha:]]+") # export all identifiers starting with letters
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)
答案 1 :(得分:2)
对this SO post的回答和评论对我有所帮助。看来我需要
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。 / p>
UPDATE2
我已经在this blog post