【问题标题】:Rcpp, making functions available to R from DLLRcpp,使函数可以从 DLL 中用于 R
【发布时间】:2018-11-03 21:50:13
【问题描述】:

C++ 新手,我想让在 DLL 中编译的函数在 R 中可用。

到目前为止,我通过在 VisualStudio 中遵循 these steps,然后使用 R 中的 dyn.load 加载创建的 dll,成功地为一个以 integer 作为输入并返回相同的基本函数做到了这一点。

但是,我的 C++ 函数需要处理 R data.frame 对象,我不确定如何实现。我从the Rcpp gallery 看到Rcpp 可能包含R 和c++ 数据类型之间的某种转换,包括data.frame 对象,但我不知道我是否可以使用Rcpp 生成一个dll,然后我可以将其包含在其中R 使用dyn.load

this answer by Dirk Eddelbuettel 看来,使用Rcpp 生成“动态库”似乎是可能的,但是,当我尝试使用rcpp.package.skeleton() 生成带有源.cpp 文件的包时,我找不到任何dll。我想要一个 dll 的函数来自the Rcpp gallery

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
DataFrame modifyDataFrame(DataFrame df) {
  // access the columns
  IntegerVector a = df["a"];
  CharacterVector b = df["b"];

  // make some changes
  a[2] = 42;
  b[1] = "foo";       
  // return a new data frame
  return DataFrame::create(_["a"]= a, _["b"]= b);
}

我尝试将该代码粘贴到 VisualStudio 中以尝试生成该 DLL,但是我遇到了我非常期待的错误“找不到 Rcpp.h”。

然后我在 RStudio 中按照以下步骤操作:

  1. 创建新项目/包
  2. 包含这个 cpp 源文件作为这个包的源文件
  3. include rcpp 并输入Rcpp.package.skeleton("mypackage") 到目前为止,包文件夹中没有DLL
  4. 尝试通过转到构建/安装并重新启动在 RStudio 中构建包,但随后我收到一条错误消息“构建 R 包需要安装其他构建工具,您要安装它们吗?”但是我已经安装了 RbuildTools 3.4,当我在 RStudio 中单击“是”时,没有任何反应。

PS:很高兴听到其他方法,但如果可能,应该使用 DLL 格式。非常感谢任何信息,因为我基本上不知道 Rcpp 或 C++ 是如何工作的

【问题讨论】:

  • 首先:在我们丰富的文档中,我们要求您在哪里使用 Visual Studio ?正确答案,无处可去。事实上,Rcpp FAQ 明确表示不要。第二:Rcpp.package.skeleton() 创建 sources 而 DLL 是 compile and link 步骤的结果。你编译链接了吗?
  • 我使用 VisualStudio 的原因是我还没有在您的大量文档中找到如何在独立 DLL 中提供函数 - 如果我错过了这一点,请指出正确的来源,谢谢
  • 1.创建一个包含待编译源代码的包,例如通过Rcpp.package.skeleton()。 2. 构建包,例如通过R CMD buildR CMD INSTALL(或通过点击RStudio 中的按钮)。如果在第 1 步和第 2 步之间复制了 src/ 目录中的有效文件,它将成为包共享库的一部分。 这就是 R 的工作原理,并且与 Rcpp 本身无关。另请注意,只有使用 R 的操作系统定义了术语“DLL”。所以不要沉迷于它——Linux 和 macOS 将其称为共享库文件,分别扩展名为 .so.dylib
  • 最重要的是:不要制定自己的规则(即:“使用 Visual Studio 编译”)并期望事情会像那样工作。这个世界不欠你这个人情。
  • 我根本没有试图编造任何规则,只是使用我在网上找到的内容。我在这里谦虚地请求帮助和澄清,但如果你要使用这种语气,我会要求你弃权。我敢肯定,在 StackOverflow 之外,我们都有很多事情要处理

标签: c++ r rcpp


【解决方案1】:

您需要弄清楚为什么您的设置会受到影响。这意味着很容易而且很容易。观看:

R> Rcpp::cppFunction('DataFrame modDF(DataFrame df) { IntegerVector a = df["a"]; CharacterVector b = df["b"]; a[2] = 42; b[1] = "foo"; return DataFrame::create(Named("a")=a, Named("b")=b); } ')                  
R> df <- data.frame(a=1:3, b=letters[24:26])                                                                                                                                                                       
R> df                                                                                                                                                                                                              
  a b                                                                                                                                                                                                              
1 1 x                                                                                                                                                                                                              
2 2 y                                                                                                                                                                                                              
3 3 z                                                                                                                                                                                                              
R> modDF(df)                                                                                                                                                                                                       
   a   b                                                                                                                                                                                                           
1  1   x                                                                                                                                                                                                           
2  2 foo                                                                                                                                                                                                           
3 42   z                                                                                                                                                                                                           
R>      

现在,我显然不建议用这种方式写一篇很长的单行。 你已经在正确的轨道上设置一个包。但是你需要弄清楚是什么阻碍了你的工具。

作为 PS,上面的单行具有更好的缩进:

R> Rcpp::cppFunction('DataFrame modDF(DataFrame df) { \
      IntegerVector a = df["a"]; \
      CharacterVector b = df["b"]; \
      a[2] = 42;  \
      b[1] = "foo"; \ 
      return DataFrame::create(Named("a")=a, Named("b")=b); \
    } ')                  

【讨论】:

    【解决方案2】:

    以下似乎有效:

    1. 来自 R,运行 Rcpp.package.skeleton("dfcpp4", cpp_files="modifyDataFrame.cpp")。为了使modifyDataFrame 函数可以从dll 使用dyn.load 使用,第二个参数是必需的。
    2. 从命令行运行R CMD build dfcpp4
    3. 从命令行运行R CMD check dfcpp4 --no-manual
    4. dll 文件现在存在于 src-x64 文件夹中

    我现在可以使用

    调用此函数
    dyn.load("dfcpp4/src-x64/dfcpp4.dll")
    df <- data.frame(a = c(1, 2, 3),
                     b = c("x", "y", "z"))
    .Call("_dfcpp4_modifyDataFrame", df)
       a   b
    1  1   x
    2  2 foo
    3 42   z
    

    我不明白为什么在这种情况下应该使用.Call 而不是.C...

    【讨论】:

    • 看在 Pete 的份上,请阅读少量 Rcpp 文档——例如 updated Rcpp Introduction vignette。您确实不需要自己致电dyn.load()。您确实不需要自己致电.Call()。 Rcpp Attributes 及其代码生成器都为您服务。例如查看包RcppExamples
    • 在将 C++ 文件复制到 src/ 后,只需调用 Rcpp::compileAttributes()。它将更新src/RcppExports.cppR/RcppExports.R。构建和安装后,您现在应该拥有modifyDataFrame() 可直接从 R 调用
    • 请阅读问题,我现在确实想安装包,我只想使用 dll。
    • 你还是误会了。 dll没关系。它是一种副产品。它是为您制作的,并且隐藏在包或工具中(即Rcpp::cppFunction())。您的问题可能是您上面的第 4) 点:更正您的 RStudio / Rtools 设置,这一切都变得轻而易举。除非我们无视你,否则你在浪费你的时间和我们的时间。
    • 如果您想分解命令,请查看带有 inline 包的旧示例,也许还有我从 2009 年到 2012 年左右的一些旧幻灯片——仍然张贴在我的网站上。他们有所有老式的例子。如果你必须,你可以。 手动调用dyn.load() 仍然是“错误的”,因为您现在引入了我们目前没有的操作系​​统依赖项。 您的调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    相关资源
    最近更新 更多