我实现了Python-style dictionary for R,但是当给定的键在字典中没有值时,没有找到引发错误的好方法。调用stop
很容易,但我想通过打印R对象告诉用户找不到哪个键。现在我有:
Rcpp::Rcout << "Key not found: ";
Rcpp::print(key); # <-- how can I get this on stderr?
Rcpp::stop("Key error!");
这会将消息打印到stdout,但我宁愿在stderr上使用它。可能我只是缺少Rcpp提供的功能?
这是一个MWE:
library(Rcpp)
sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key) {
Rcpp::print(key);
Rcpp::Rcerr << "This does not work: " << key << std::endl;
}
/*** R
test("x")
test(c(1,2,3))
*/
')
答案 0 :(得分:5)
这很好用:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
std::string test(std::string key) {
Rcpp::Rcerr << "Key not found: "<< key << std::endl;
Rcpp::stop("Key error!");
return key;
}
/*** R
test("x")
*/
输出:
Key not found: x
Error in eval(expr, envir, enclos) : Key error!
修改强>
好的,所以你传递一个可以是单个值或向量的SEXP。我建议将其转换为字符向量:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key) {
CharacterVector key1 = as<CharacterVector>(key);
Rcpp::Rcerr << "This does not work: " << key1 << std::endl;
}
/*** R
test(c("x", "y"))
test(1:3)
*/
输出:
> Rcpp::sourceCpp('E:/temp/ttt.cpp')
> test(c("x", "y"))
This does not work: "x" "y"
> test(1:3)
This does not work: "1" "2" "3"
答案 1 :(得分:1)
此刻,似乎这种黑客行为是唯一的出路。它不是非常有效,因为我们从C ++返回到R以获得值作为一个很好的字符串。
library(Rcpp)
sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key, Function generate_error) {
std::string s = as<std::string>(generate_error(key));
stop(s);
}
/*** R
generate_error <- function(key) {
paste("Key not found:", capture.output(print(key)))
}
try( test("x", generate_error) )
try( test(c(1,2,3), generate_error) )
*/
')
答案 2 :(得分:0)
Rcpp calls Rf_PrintValue。我已经浏览了R源代码,看起来这个函数依次使用printf
来实现。
因此,问题是如何将外部printf
调用重定向到stderr
。根据您的平台,您有多个选项,例如dup
/ freopen
/ CreatePipe
等。可以说,来回重定向stdout
是一种黑客行为。