如何从 C 获取 FILE * 到 R 控制台

How to get a FILE * to the R console from C

我正准备向 CRAN 提交一个 R 包,我正在处理来自 R CMD 检查的最后一条注释。请注意,我参考了标准输出。 “Writing R Extensions”手册对这个问题有这样的说法:

Compiled code should not write to stdout or stderr and C++ and Fortran I/O should not be used. As with the previous item such calls may come from external software and may never be called, but package authors are often mistaken about that.

在我的所有代码中,我都确保在需要写东西时调用 Rprintf 或 REprintf,但我还有一个地方无法进行此切换:Flex 生成的代码。

我使用 GNU Flex/Bison 来解析 DSL,而 Flex 有自己的指针和引用,用于诸如写入标准输出之类的事情。具体来说,它有它所谓的 yyout ,我可以用 yyout_set 函数覆盖它。伟大的!但是我应该把它设置成什么?

我遇到的问题是我无法更改(生成的)C 代码来调用 REprintf,但我不知道 R 是否导出 FILE * 我可以用来覆盖 yyout.我尝试深入研究 R 源代码,但不知道该去哪里找。

是否有 FILE * 可用于写入 R 控制台?如果没有,是否有有时可以接受的解决方案?我从来没有向 CRAN 提交过包,但我的印象是这不会通过召集。

对于这个问题,我有一个两部分的解决方案,似乎可以解决问题。请注意,我使用的是 Flex/Bison 的可重入选项,因此这可能对每个人都不完全一样。

我定义 ECHO 以在我的词法分析器代码的序言中使用 Rprintf

我实际上已经有了定义 YY_FATAL_ERROR 的代码,所以我在其中添加了 ECHO 代码。我将以下代码添加到我的 .l 文件的序言中:

#ifdef __GNUC__
    /* this is for functions that don't return */
#   define NORETURN __attribute__((noreturn))
#else
#   define NORETURN
#endif

void NORETURN Rf_error(const char *, ...);
void Rprintf(const char *, ...);
#define YY_FATAL_ERROR(msg) Rf_error( msg )
#define ECHO Rprintf(yytext)

Rf_error 是 R 的 error 所调用的,因此它是出现不可恢复错误时的正确函数。我继续为 GCC 属性定义了一个宏,以避免有关函数未返回的警告。

我从生成的源代码中删除了将 yyout 设置为 stdout 的行。

.yy.c 文件中,在 YY_DECL 函数中,删除以下行:

                if ( ! yyout )
                        yyout = stdout;

我写了一个简单的脚本来做到这一点。如果您不经常重新生成此文件,我想您可以手动完成。