[英]Is it possible to “grab”/“scrape” the .Call() output of C printf() within R (or with Rprintf())?
我正在使用R代碼,它通過.Call()
與C接口。 C函數通過printf()
輸出到STDOUT。 作為一個具體的,更簡單的例子,我將關注http://mazamascience.com/WorkingWithData/?p=1099
這是我們的C代碼,通過printf()
, helloA1.c
輸出hello world:
#include <R.h>
#include <Rdefines.h>
#include <stdio.h>
SEXP helloA1() {
printf("Hello World!\n");
return(R_NilValue);
}
通過R CMD SHLIB helloA1.c
安裝后,我們在R中調用如下函數:
> dyn.load("helloA1.so")
> hellocall = .Call("helloA1")
Hello World!
我無法訪問“Hello World!”文本。 但是在R中作為數據結構。 例如
> vec1 = as.vector( .Call("helloA1"))
Hello World!
> vec1
NULL
>
要么
> library(data.table)
> dt = as.data.table(.Call("helloA1"))
Hello World!
> dt
Null data.table (0 rows and 0 cols)
>
有沒有辦法將printf()
的輸出“加載”到R?
我可以將函數轉換為Rcpp,但是我會遇到與Rprintf()
相同的問題。
編輯:抱歉,我以前以為RPrintf()
是內部的功能Rcpp
。 我已恰當地編輯了這個問題的標題。
所以,這里的問題是printf
否定了R的內置輸出收集機制。 特別是,沒有C級“stdout”文件流,因此,在Rgui或RStudio中沒有要收集的輸出。 有關詳細信息,請參見第6.5節 “ 寫入R擴展的 打印 ”
兩種可能的解決方
printf
設置為Rprintf
並包含#define STRICT_R_HEADERS
以避免錯誤 。 Rprintf
printf
實例切換為Rprintf
。 從這里開始,捕獲可以傳遞給capture.output()
,它直接將輸出分配給變量,或者傳遞給sink()
,它將輸出重定向到一個文件,然后必須使用readLines()
讀回其內容。 后者使得可以在多行代碼上清楚地封閉以捕獲輸出,而先前關注於確保輸入表達式中存在的輸出。
對於第一次迭代,只需定義包含自定義定義的頭,然后包含第三方庫,例如
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
我在R包中實現了這種方法,可以在這里找到:
https://github.com/coatless/printf2Rprintf
此選項手動重新定義printf
函數。
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.