0

我正在尝试inst/extdata从 Rcpp Catch2 测试访问文件上的数据文件。文件树如下所示:

├── inst
│   └── extdata
│       └── data-sample
├── R
│   ├── catch-routine-registration.R
│   └── RcppExports.R
├── src
    ├── mycode.cpp
    ├── RcppExports.cpp
    ├── Package_types.h
    ├── test-example.cpp
    └── test-runner.cpp

我相信,这与您从使用 devtools 的新包骨架中获得的内容相似。现在,我可以data-sample像这样轻松地从 testthat 测试中访问这个文件:

system.file(
    "extdata", "data-sample", package = "Package", mustWork = TRUE
)

并根据需要使用它。我知道此时这使用了已安装包中的全局路径,但是我找不到将这个值传递给我的 c++ 测试的方法。我目前正在使用硬编码路径,但这显然只适用于我的机器。

这是我目前正在使用的:

const std::string DATAFILE = "/my/package/inst/extdata/data-sample";

由于这是一个读取文件的函数,我真的无法以任何方式嵌入它,但我仍然想知道:如何将 R 数据传递给 Rcpp/Catch 测试?

提前致谢!

4

3 回答 3

3

您可以system.file()通过从 C++ 调用 R 函数来获取路径,即使它不是导出的 C++ 函数(这就是我在对帖子的评论和 Dirk Eddelbuettel 的回答之后解释您的查询的方式)。考虑以下 C++ 代码print_extdata.cpp

#include <Rcpp.h>

Rcpp::StringVector get_extdata(){
    Rcpp::Environment base("package:base");
    Rcpp::Function sys_file = base["system.file"];
    Rcpp::StringVector res = sys_file("extdata", "2012.csv",
                                      Rcpp::_["package"] = "testdat");
    return res;
}


// [[Rcpp::export]]
void print_extdata() {
    Rcpp::StringVector path = get_extdata();
    Rcpp::Rcout << path;
}

然后从 R 调用:

> Rcpp::sourceCpp("print_extdata.cpp")
> print_extdata()
"/home/duckmayr/R/x86_64-pc-linux-gnu-library/3.5/testdat/extdata/2012.csv"
于 2018-10-24T23:46:02.273 回答
2

我将此添加为另一个答案,因为我只是从 Dirk 和 Dukemayr 的答案中得到的。

我发现 Rcpp 测试时的包还没有被加载,所以 Dukemayr 的回答没有开箱即用。但是,经过一番摆弄,我发现他的代码在仅使用package选项调用时会输出当前项目路径,因此我发现此时将加载包,但是使用项目存储库中的路径。

这确实有点令人困惑,因为使用 R 的测试按预期使用 R 安装文件夹(例如。/home/user/R/x86_64-pc-linux-gnu-library/3.5/)。我需要更深入地了解为什么会这样。

最后,我使用了这个函数来获取测试中的路径:

#include <Rcpp.h>
#include <string>

std::string get_datapath_fromR(std::string filename, std::string packageName)
{
    Rcpp::Environment base("package:base");
    Rcpp::Function sys_file = base["system.file"];
    // "inst" field is necessary at this point
    Rcpp::StringVector file_path_sv = sys_file(
        "inst", "extdata", filename,
        Rcpp::_["package"] = packageName,
        Rcpp::_["mustWork"] = true
    );
    std::string file_path = Rcpp::as<std::string>(file_path_sv);
    return file_path;
}

我可以在这样的测试中调用它:

...
std::string datafile = get_datapath_fromR("data-sample", "package");        
...

结果得到这个:/home/user/path/to/package/folder/packageName/inst/extdata/data-sample

于 2018-10-25T17:23:40.257 回答
2

不要使用硬编码路径。试着弄清楚你是否需要

  • 包构建时间,然后它将是../inst/extdata/data-sample/foo.csv,或者

  • 一旦安装,在这种情况下它是标准的system.file("extdata/foo.csv", package="yourpackage")

这对于一般的 R 包来说是一个问题——但即使你这样做R CMD check了,它实际上也会先安装包,所以你处于第二种情况。

说得通?

于 2018-10-24T23:17:40.467 回答