gpt4 book ai didi

c - 是否有可能 "grab"/"scrape"C printf() 在 R 中(或使用 Rprintf())的 .Call() 输出?

转载 作者:行者123 更新时间:2023-12-04 10:37:14 25 4
gpt4 key购买 nike

我正在使用 R 代码,该代码通过 .Call() 与 C 接口(interface)。 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 中收集的输出。详情请见Section 6.5 PrintingWriting R Extensions

两种可能的解决方案:

  1. 定义一个宏,将 printf 设置为指向 Rprintf 并包含 #define STRICT_R_HEADERS to avoid errors .
  2. 将违规代码中的 printf 实例切换为 Rprintf

从这里,捕获可以传递给 capture.output() ,它直接将输出分配给一个变量,或者 sink() , 它将输出重定向到一个文件,然后必须使用 readLines() 读回该文件的内容.后者可以清楚地包含多行代码以捕获输出,而先验则专注于确保输入表达式中存在的输出。

选项1

对于第一次迭代,只需定义一个包含自定义定义的 header ,然后包含第三方库,例如

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

选项 2

此选项手动重新定义 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

关于c - 是否有可能 "grab"/"scrape"C printf() 在 R 中(或使用 Rprintf())的 .Call() 输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48312317/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com