我想编写一个程序来使用 RInside 执行 R 命令并判断结果是否为字符串。我创建了一个 RInside 实例并使用它的方法RInside::parseEval来解析 R 命令,然后将结果存储在 SEXP 变量中。我使用TYPEOF检查结果的类型是否为字符串,然后使用其构造函数将其转换为Rcpp::String。问题是,当我尝试解析诸如之类的错误命令时,程序的行为变得有些不可预测。程序如下图所示:paste('hello
#include <RInside.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
RInside *R = new RInside();
const char *expr = argv[1];
SEXP res = NULL;
try{
res = R->parseEval(expr);
} catch (std::exception &e) {
res = NULL;
printf("Exception thrown\n");
}
printf("res points to %p\n", res);
if (res != NULL && TYPEOF(res) == STRSXP) {
Rcpp::String res_str = res;
printf("The result is a string: %s\n", res_str.get_cstring());
} else {
printf("The result is not a string");
}
}
当我用 agrument 运行程序时"paste('hello'"
,我得到了输出
res 指向 0x7f0ca84e14d0
结果不是字符串
但是,当我将代码打包成一个函数时,如图所示:
#include <RInside.h>
#include <stdio.h>
void test_R(RInside *R, const char *expr)
{
SEXP res = NULL;
try{
res = R->parseEval(expr);
} catch (std::exception &e) {
res = NULL;
printf("Exception thrown\n");
}
printf("res points to %p\n", res);
if (res != NULL && TYPEOF(res) == STRSXP) {
Rcpp::String res_str = res;
printf("The result is a string: %s\n", res_str.get_cstring());
} else {
printf("The result is not a string");
}
}
int main(int argc, char* argv[])
{
RInside *R = new RInside();
const char *expr = argv[1];
test_R(R, expr);
}
并使用与以前相同的命令行参数运行它"paste('hello'"
,我得到了输出
res 指向 (nil)
结果不是字符串
所以我的问题是,为什么它会这样?当使用 解析错误命令时RInside::parseEval
,是否会引发异常或结果是否为 NULL 指针,或者至少会发生其中一种情况?我上面的代码是否正确地完成了它的工作?
任何帮助将不胜感激。
编辑0:
在花了一些时间阅读代码之后,R 似乎将该命令paste('hello
视为“不完整”,这意味着如果我们稍后发送另一个命令来“完成”它,它将成功执行。
#include <RInside.h>
#include <stdio.h>
void test_R(RInside *R, const char *expr, int is_ok)
{
SEXP res = R->parseEval(expr);
if (is_ok) {
std::string res_str = Rcpp::String(res);
printf("The result is %s\n", res_str.c_str());
}
}
int main()
{
RInside R;
const char *head = "paste('hello";
const char *tail = "')";
test_R(&R, head, 0); // This will parse "paste('hello"
test_R(&R, tail, 1); // This will parse the rest of the command
}
上面代码的结果是
结果你好