I'm working with R code that has an interface to C via .Call(). The C function outputs to STDOUT via printf(). As a concrete, more simple example, I'll follow http://mazamascience.com/WorkingWithData/?p=1099
Here is our C code with outputs hello world via printf(), helloA1.c:
#include <R.h>
#include <Rdefines.h>
#include <stdio.h>
SEXP helloA1() {
printf("Hello World!\n");
return(R_NilValue);
}
After installation via R CMD SHLIB helloA1.c, we invoke the function as follows within R:
> dyn.load("helloA1.so")
> hellocall = .Call("helloA1")
Hello World!
I cannot access the text "Hello World!" within R as a data structure though. e.g.
> vec1 = as.vector( .Call("helloA1"))
Hello World!
> vec1
NULL
>
or
> library(data.table)
> dt = as.data.table(.Call("helloA1"))
Hello World!
> dt
Null data.table (0 rows and 0 cols)
>
Is there any way to "load" the output of printf() into R?
I can translate the functions into Rcpp, but will run into the same problem I think with Rprintf().
EDIT: Apologies, I had previously thought RPrintf() was a function within Rcpp. I have edited the title of this question appropriately.
So, the issue here is printf negates R's built collection mechanisms for output. In particular, there is no C-level 'stdout' file stream and, thus, no output to collect in either Rgui or RStudio. For details, please see Section 6.5 Printing
of Writing R Extensions
Two possible solutions:
printf to direct into Rprintf and include the #define STRICT_R_HEADERS to avoid errors.printf to Rprintf in the offending code.From here, the capture can be passed off to either capture.output(), which directly assigns output to a variable, or sink(), which redirects output to a file whose contents must then be read back in using readLines(). The latter makes it possible to have a clear enclose over multiple lines of code to capture output while the prior is focused on securing output present from an inputted expression.
For the first iteration, just define a header that includes the custom define and then include the third party library, e.g.
my_code.h
#ifndef MY_CODE_H
#define MY_CODE_H
#include <R.h>
// this load R_ext/Print.h.
// #include <YOUR_LIBRARY.h>
// Define strict headers
#define STRICT_R_HEADERS
// Map printf to Rprintf
#define printf Rprintf
#endif
toad.c
#include <R.h>
#include <Rdefines.h>
#include "my_code.h"
SEXP helloA1() {
printf("Hello World!\n");
return(R_NilValue);
}
toad_example.R
system("R CMD SHLIB ~/Desktop/toad.c")
dyn.load("~/Desktop/toad.so")
helloA1 <- function() {
result <- .Call("helloA1")
}
# Gregor's suggestion
captured_data = capture.output(helloA1())
# Using sink around multiple function calls to redirect output
# to a single file
sink("sink-examp.txt")
helloA1()
sink()
input_data = readLines("sink-examp.txt")
all.equal(input_data, captured_data)
# [1] TRUE
I've implemented this approach in an R package that can be found here:
https://github.com/coatless/printf2Rprintf
This option manually redefines the printf functions.
toad.c
#include <R.h>
#include <Rdefines.h>
SEXP helloA1() {
Rprintf("Hello World!\n"); // manually changed
return(R_NilValue);
}
toad_example.R
system("R CMD SHLIB ~/Desktop/toad.c")
dyn.load("~/Desktop/toad.so")
helloA1 <- function() {
result <- .Call("helloA1")
}
# Gregor's suggestion
captured_data = capture.output(helloA1())
# Using sink around multiple function calls to redirect output
# to a single file
sink("sink-examp.txt")
helloA1()
sink()
input_data = readLines("sink-examp.txt")
all.equal(input_data, captured_data)
# [1] TRUE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With