Я пытаюсь получить доступ к файлу данных в файле 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 из теста test, вот так:
system.file(
"extdata", "data-sample", package = "Package", mustWork = TRUE
)
И используйте его по мере надобности. Я знаю, что на данный момент здесь используется глобальный путь из установленного пакета, однако я не могу найти способ передать это значение в мои тесты C++. В настоящее время я использую жестко запрограммированный путь, но он, очевидно, работает только на моей машине.
Вот что я сейчас использую:
const std::string DATAFILE = "/my/package/inst/extdata/data-sample";
Поскольку это функция для чтения файлов, я действительно не могу встроить ее каким-либо образом, но я все еще хочу знать: как передать данные R в тесты Rcpp / Catch?
Заранее спасибо!
@duckmayr Да, это решило бы мою проблему, однако мне нужно передать это на C++, который вызывается R. Поскольку это тестовый файл, я не могу передать ему Function.





Не используйте жестко запрограммированный путь. Попробуйте разобраться, нужно ли вам в
время сборки пакета и тогда это будет ../inst/extdata/data-sample/foo.csv, или
один раз установлены и в этом случае это стандартный system.file("extdata/foo.csv", package = "yourpackage")
Это небольшая проблема для пакетов R в целом, но даже когда вы используете R CMD check, на самом деле это сначала устанавливает пакет, так что вы находитесь во втором случае.
Имеет смысл?
Да, мне нужен именно этот второй футляр. Однако как я могу передать это в тесты C++? Я не думаю, что мой вопрос оставил это ясным, но это основная проблема, с которой я столкнулся. Я могу протестировать второй случай в тестах R, как хочу, но не если я хочу провести аналогичный тест в Rcpp, который я не могу (или лучше не хочу) подвергать R. хотите знать, как передать этот путь к файлу system.file после его установки в тесты Catch.
Вы можете получить путь system.file(), вызвав функцию R из C++, даже если это не экспортированная функция C++ (именно так я интерпретировал ваш запрос, следуя комментариям к сообщению и ответу Дирка Эддельбюттеля). Рассмотрим следующий код 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"
Принято, потому что это было именно то, что мне было нужно, спасибо! Я обнаружил, что пакет в настоящее время не зарегистрирован на стороне тестирования, поэтому, хотя он работает в обычном сеансе R / при использовании пакета, я не могу понять, почему он не может найти пакет во время тестирования ... Я посмотрю на него подробнее.
Я добавляю это как еще один ответ, так как я получил его только из ответов Дирка и Дакмайра.
Я обнаружил, что пакет во время тестирования Rcpp еще не был загружен, поэтому ответ duckmayr не сработал из коробки. Однако после некоторой игры я обнаружил, что его код, когда он вызывается только с опцией 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
Вы спрашиваете, как получить возвращаемое значение вызова функции R
system.file("extdata", "data-sample", package = "Package", mustWork = TRUE)из C++?