首页 > 解决方案 > Rcpp:无法访问同一包的 R 代码中的模块类

问题描述

假设我想在 R 中构建一个包含 c++ 代码的非常简单的包。
我的测试项目将被称为香蕉

假设我有一个名为“ bananas ”的文件夹,其中我有另外两个文件夹,一个名为c++,一个名为R

c++文件夹中,我有一个名为include的文件夹,其中包含 香蕉.hpp头文件(带有类定义):

#ifndef BANANAS_H
#define BANANAS_H

class Bananas
{
  public:
  void add_banana();
  int get_bananas();

  protected:
  int number_of_bananas;
};

#endif

外部包括实现香蕉.hpp方法的 香蕉.cpp文件:

#include "include/bananas.hpp"
using namespace std;

void Bananas::add_banana(){
    // Return False if edge already existed
    number_of_bananas ++;
}

int Bananas::get_bananas(){
    return number_of_bananas;
}

现在在我的R文件夹中,我有一个wrapper.cpp文件,它使用 Rcpp 库将 R 中的 c++ 类作为模块导出:

#include <Rcpp.h>
#include "include/bananas.hpp"

using namespace Rcpp;

RCPP_EXPOSED_CLASS(Bananas)

RCPP_MODULE(Bananas_cpp){

  class_<Bananas>("BananasCPP")
  .default_constructor()
  .method("add_banana", &Bananas::add_banana)
  .method("get_bananas", &Bananas::get_bananas)
  ;
}

请注意,现在#include "include/bananas.hpp"并不意味着什么,但将来这个文件将被添加到 source.xml 中。最后,我主要关心的是这个类的 R 包装器:

require(R6)
library(Rcpp)

# For exposing the error
print(ls(all.names = TRUE))

# Load Module
bcpp <- Module("Bananas_cpp", PACKAGE="RBananasC", mustStart = TRUE)$BananasCPP

Bananas <- R6Class("Bananas", list(
   bn = new(bcpp),
   print_bananas = function() {print(self$bn$get_bananas())},
   banana_tree = function(d) {
     for(row in 1:d){
        self$bn$add_banana()
     }
   }
 ))

现在在我的主目录中运行setup.R文件时,如下所示:

require(Rcpp)

# Make a base package
unlink("RBananasC", recursive=TRUE)
Rcpp.package.skeleton(name = "RBananasC", list = character(), 
                      path = ".", force = FALSE, 
                      cpp_files = c("bananas/R/wrapper.cpp", "bananas/c++/bananas.cpp", "bananas/c++/include/bananas.hpp"))
dir.create("RBananasC/src/include")
file.rename("RBananasC/src/bananas.hpp", "RBananasC/src/include/bananas.hpp")
install.packages("RBananasC", repos=NULL, type="source")

# See that Bananas_cpp works
library(RBananasC) #Without this line it doesn't work

print(Module("Bananas_cpp", PACKAGE="RBananasC", mustStart = TRUE)$BananasCPP)
bcpp <- Module("Bananas_cpp", PACKAGE="RBananasC", mustStart = TRUE)$BananasCPP
ban <- new(bcpp)
ban$add_banana()
print(ban$get_bananas())

# Make the desired package
unlink("RBananas", recursive=TRUE)
Rcpp.package.skeleton(name = "RBananas", list = character(), 
                      path = ".", force = FALSE, 
                      code_files = c("bananas/R/bananas.R"), cpp_files = c("bananas/R/wrapper.cpp", "bananas/c++/bananas.cpp", "bananas/c++/include/bananas.hpp"))
dir.create("RBananas/src/include")
file.rename("RBananas/src/bananas.hpp", "RBananas/src/include/bananas.hpp")
install.packages("RBananas", repos=NULL, type="source")

我的香蕉.R文件中有一个非常奇怪的行为,这与我的包的Bananas_cpp模块不可见有关,因此我无法在安装时访问BananasCPP类。另一方面,如果我忽略文件bananas.R ,我可以从包RBananasC的模块Bananas_cpp导入BananasCPP,我使用Rcpp.package.skeleton创建。

总结一下整个文件结构如下:

.
├── bananas
│   ├── c++
│   │   ├── bananas.cpp
│   │   └── include
│   │       └── bananas.hpp
│   └── R
│       ├── bananas.R
│       └── wrapper.cpp
└── setup.R

为了证明我的问题是什么,您只需运行setup.R

我遵循了一个标准教程,但是在互联网上搜索几天时,我找不到任何有关如何从Bananas.R包装函数Bananas中的Bananas_cpp模块加载BananasCPP类的信息。这个文件没有出现在包内活动环境的命名空间中,所以我认为应该解决这个问题:“我应该添加哪些命令以及在包的当前命名空间内公开我的Bananas_cpp模块的位置”。

当然,这是我从我遇到的实际问题中复制出来的。多谢您的支持!

标签: c++rrcpp

解决方案


推荐阅读