I want to write a program to execute an R command using RInside and tell whether or not the result is a string. I created a RInside instance and used its method RInside::parseEval to parse the R command and then stored the result in a SEXP variable. I used TYPEOF to check if the type of the result is a string and then casted it to Rcpp::String using its constructor. The problem is that when I try to parse an error command such as paste('hello
, the program's behavior becomes somewhat unpredictable. The program is showed below:
#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");
}
}
When I ran the program with the agrument "paste('hello'"
, I got the output
res points to 0x7f0ca84e14d0
The result is not a string
However, when I packed the code into a function, as shown:
#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);
}
and ran it with the same command line argument "paste('hello'"
as before, I got the output
res points to (nil)
The result is not a string
So my question is, why does it behave that way? When one parses an error command with RInside::parseEval
, will an exception be thrown or will the result be a NULL pointer or will at least one of those cases happen? Does my code above properly do its job?
Any help will be thankful.
Edit 0:
After spending some time to read the code, it appears that R treats the command paste('hello
as "incomplete", which means that if we later send another command to "complete" it, it will be successfully executed.
#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
}
The result of the code above is
The result is hello