【问题标题】:How to use a user-defined data C structure into an R package如何在 R 包中使用用户定义的数据 C 结构
【发布时间】:2020-10-25 06:39:31
【问题描述】:

当我“获取”文件时,这个最小的例子会编译:

/*
        read_header.c
*/

#include <stdio.h>
#include <stdlib.h>

#include <RcppCommon.h>

typedef struct {
    int my_data;
} MY_HEADER_INFO;

namespace Rcpp {
  template <> SEXP wrap(const MY_HEADER_INFO& x);
}

#include <Rcpp.h>
namespace Rcpp {
 template <>
 SEXP wrap(const MY_HEADER_INFO& x) {
   std::vector<std::string> names;
   std::vector<SEXP> elements(1);
   // do something with the elements and names
   names.push_back("my_data");
   elements[0] = Rcpp::wrap( x.my_data );
 };
}

//' @export
// [[Rcpp::export]]
MY_HEADER_INFO read_header() {
    MY_HEADER_INFO *header;
  
  header = (MY_HEADER_INFO*)malloc(sizeof(MY_HEADER_INFO));
  memset(header, 0, sizeof(MY_HEADER_INFO));
  
    return *header;
}

当我尝试在 RStudio 中将其构建成一个包 (CMD + SHIFT + B) 时,我收到以下很长的错误消息,清楚地列出了问题是我的用户定义的返回结构 MY_HEADER_INFO:

描述

Package: myPackage
Type: Package
Title: What the Package Does (Title Case)
Version: 0.1.0
Depends: R (>= 4.0.0)
License: GPL-3
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.1.0
Imports:
    Rcpp
Suggests: 
    knitr,
    rmarkdown,
    testthat
VignetteBuilder: knitr
LinkingTo: 
    Rcpp

命名空间

# Generated by roxygen2: do not edit by hand

export(read_header)

我收到以下错误:

==> Rcpp::compileAttributes()

* Updated src/RcppExports.cpp
* Updated R/RcppExports.R

==> devtools::document(roclets = c('rd', 'collate', 'namespace'))

Updating myPackage documentation
Loading myPackage
Re-compiling myPackage
─  installing *source* package ‘myPackage’ ...
   ** using staged installation
   ** libs
   clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG  -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I/usr/local/include   -fPIC  -Wall -g -O2  -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c RcppExports.cpp -o RcppExports.o
   RcppExports.cpp:9:1: error: unknown type name 'MY_HEADER_INFO'
   MY_HEADER_INFO read_header();
   ^
   1 error generated.
   make: *** [RcppExports.o] Error 1
   ERROR: compilation failed for package ‘myPackage’
─  removing ‘/private/var/folders/gl/jvj9b0xn34lgq6_h9370p8q80000gn/T/RtmpLKsw0o/devtools_install_1f333d54be59/myPackage’

Error: System command 'R' failed, exit status: 1, stdout + stderr:
E> * installing *source* package ‘myPackage’ ...
E> ** using staged installation
E> ** libs
E> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG  -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I/usr/local/include   -fPIC  -Wall -g -O2  -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c RcppExports.cpp -o RcppExports.o
E> RcppExports.cpp:9:1: error: unknown type name 'MY_HEADER_INFO'
E> MY_HEADER_INFO read_header();
E> ^
E> 1 error generated.
E> make: *** [RcppExports.o] Error 1
E> ERROR: compilation failed for package ‘myPackage’
E> * removing ‘/private/var/folders/gl/jvj9b0xn34lgq6_h9370p8q80000gn/T/RtmpLKsw0o/devtools_install_1f333d54be59/myPackage’

 Stack trace:

 1. base:::suppressPackageStartupMessages({ ...
 2. base:::withCallingHandlers(expr, packageStartupMessage = function(c) tryInv ...
 3. devtools::document(roclets = c("rd", "collate", "namespace"))
 4. withr::with_envvar(r_env_vars(), roxygen2::roxygenise(pkg$path,  ...
 5. base:::force(code)
 6. roxygen2::roxygenise(pkg$path, roclets, load_code = load_code)
 7. roxygen2:::load_code(base_path)
 8. pkgload::load_all(path, helpers = FALSE, attach_testthat = FALSE)
 9. pkgbuild::compile_dll(path, quiet = quiet)
 10. withr::with_makevars(compiler_flags(TRUE), assignment = "+=",  ...
 11. withr:::with_envvar(c(R_MAKEVARS_USER = makevars_file), { ...
 12. base:::force(code)
 13. base:::force(code)
 14. pkgbuild:::install_min(path, dest = install_dir, components = "libs",  ...
 15. pkgbuild:::rcmd_build_tools("INSTALL", c(path, paste("--library=",  ...
 16. pkgbuild:::with_build_tools(callr::rcmd_safe(..., env = env,  ...
 17. callr::rcmd_safe(..., env = env, spinner = FALSE, show = FALSE,  ...
 18. callr:::run_r(options)
 19. base:::with(options, with_envvar(env, do.call(processx::run,  ...
 20. base:::with.default(options, with_envvar(env, do.call(processx::run,  ...
 21. base:::eval(substitute(expr), data, enclos = parent.frame())
 22. base:::eval(substitute(expr), data, enclos = parent.frame())
 23. callr:::with_envvar(env, do.call(processx::run, c(list(bin, args = real_cmd ...
 24. base:::force(code)
 25. base:::do.call(processx::run, c(list(bin, args = real_cmdargs,  ...
 26. (function (command = NULL, args = character(), error_on_status = TRUE,  ...
 27. throw(new_process_error(res, call = sys.call(), echo = echo,  ...

 x System command 'R' failed, exit status: 1, stdout + stderr:
E> * installing *source* package ‘myPackage’ ...
E> ** using staged installation
E> ** libs
E> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG  -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I/usr/local/include   -fPIC  -Wall -g -O2  -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c RcppExports.cpp -o RcppExports.o
E> RcppExports.cpp:9:1: error: unknown type name 'MY_HEADER_INFO'
E> MY_HEADER_INFO read_header();
E> ^
E> 1 error generated.
E> make: *** [RcppExports.o] Error 1
E> ERROR: compilation failed for package ‘myPackage’
E> * removing ‘/private/var/folders/gl/jvj9b0xn34lgq6_h9370p8q80000gn/T/RtmpLKsw0o/devtools_install_1f333d54be59/myPackage’ 

Execution halted

Exited with status 1.

以下内容被写入 Rcpp_exports:

// Generated by using Rcpp::compileAttributes() -> do not edit by hand
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

#include <Rcpp.h>

using namespace Rcpp;

// read_header
MY_HEADER_INFO read_header();
RcppExport SEXP _myPackage_read_header() {
BEGIN_RCPP
    Rcpp::RObject rcpp_result_gen;
    Rcpp::RNGScope rcpp_rngScope_gen;
    rcpp_result_gen = Rcpp::wrap(read_header());
    return rcpp_result_gen;
END_RCPP
}

static const R_CallMethodDef CallEntries[] = {
    {"_myPackage_read_header", (DL_FUNC) &_myPackage_read_header, 0},
    {NULL, NULL, 0}
};

RcppExport void R_init_myPackage(DllInfo *dll) {
    R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
    R_useDynamicSymbols(dll, FALSE);
}

但是,如果我尝试修改此文件,当我调用 CMD+SHIFT+B 时,所有内容都会被覆盖。 我为同一个包编写的返回标准数据类型(例如,“std::vector”)的其他 C 程序编译没有问题,无论是当我在控制台中“获取”代码时,还是将它们构建到包中时.

我已经阅读了 Rcpp 文档和相关的小插曲(甚至还买了 Dirk 的书!),但我找不到如何告诉包生成器 MY_HEADER_INFO 的定义所在的位置。如何告诉包编译器这个文件的定义在哪里?

谢谢!

【问题讨论】:

    标签: r package rcpp


    【解决方案1】:

    这看起来像是一个并非完全不常见的问题的另一个实例,对此我们确实有一个非常简单的答案,而这个答案却鲜为人知。

    简而言之,对于一个包&lt;pkg&gt;(其中&lt;pkg&gt; 是您的包名称的别名,您可以选择小写或小写。显然没有&lt;&gt;)请这样struct(或在 C++ 情况下 class) 或 typedef 或 ... 定义到文件 inst/include/&lt;pkg&gt;_types.h 中(将 &lt;pkg&gt; 替换为您的包名称)。

    如果存在这样的文件,它会自动包含在RcppExports.cpp 中,您就可以开始了。

    详细信息在Rcpp Attributes vignette,也允许一些相关的表格:

    src/<pkg>_types.h
    src/<pkg>_types.hpp
    inst/include/<pkg>_types.h
    inst/include/<pkg>_types.hpp
    inst/include/<pkg>.h
    

    inst/include/&lt;pkg&gt;_types.h 可能是最常用的一种。通过src/ 使用它的一个例子是src/RSQLite_types.h。另一方面,在inst/include/ 中使用它的一个例子是inst/include/RcppQuantuccia_types.h,另一个更大的例子是inst/include/RcppGSL_types.h

    【讨论】:

    • 谢谢你,德克!你的建议和指示让我更接近,但我仍然有问题。我使用#include &lt;Rcpp.h&gt; namespace Rcpp { typedef struct { int my_data; } MY_HEADER_INFO; } Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include/Rcpp/internal/wrap.h:523:17 将“myPackage_types.h”设置为“inst/include”:错误: static_assert 由于要求而失败 '!sizeof(Rcpp::MY_HEADER_INFO)' "无法将类型转换为 SEXP" static_assert(!sizeof(T), "无法将类型转换为 SEXP"); ^ ~~~~~~~
    • 如果可以,请发布代码链接。这在评论中基本上难以辨认。但看起来你有一个 new 错误(因为我的建议修复了前一个错误),现在你从你的类型转换为 SEXP 不起作用。现在,这对您来说“只是”一个代码/设计问题。
    • 我同意您修复了原始问题,因此我将这个问题检查为“已回答”并将提出一个新问题。谢谢!
    • 优秀。我们有一些编写as&lt;&gt;()wrap() 的指南,从Rcpp Gallery 的简单指南开始,这里可能还有一些问题。不是最简单的主题,但一旦你拥有它就非常方便......如果你想“更快”开始,还有其他选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多