我正在尝试构建一个系统,该系统允许从C ++应用程序执行任意R代码。 为了实现这一目标,该方法的核心遵循此处描述的内容:http://www.hep.by/gnu/r-patched/r-exts/R-exts_121.html
到目前为止,这对于任何R代码都可以正常工作。但是,我遇到了使用ggplot的问题。我尝试将ggplot结果图发送到png文件。如果直接在R控制台中进行操作,效果很好,但是当我使用C ++接口时,结果文件为空。
更准确地说,R代码的组织方式如下:
当简化为最小情况时,这是我的代码:
#include <QDebug>
#include <Rembedded.h>
#include <Rinternals.h>
#include <R_ext/Parse.h>
int main(int argc, char *argv[])
{
const char *argvrf[] = {"RConsole"};
int argcrf = sizeof(argvrf) / sizeof(argvrf[0]);
Rf_initEmbeddedR(argcrf, (char**)argvrf);
// Create some dummy data for a ggplot.
// For the purpose of this minimal example, R code is just directly defined as a QString here.
QString RScript = "library(\"ggplot2\") \n" ;
RScript += "id<-c(1,2,3,4,5) \n" ;
RScript += "names<-c(\"A\",\"B\",\"C\",\"D\",\"E\") \n" ;
RScript += "notes<-c(12,20,13,15,10) \n" ;
RScript += "df1<-data.frame(id,names,notes) \n" ;
// Define a file as graphicsDevice (adapt adress to your own filesystem)
RScript += "png(\"C:/Users/Evain/Desktop/tests/testggplot.png\", width=480, height=480, res=72) \n" ;
// Drawing the ggplot.
RScript += "ggplot(data=df1,aes(x=id,y=notes))+geom_line() \n" ;
// Closing the graphic device.
RScript += "dev.off() \n" ;
ParseStatus status;
SEXP cmdSexp, cmdexpr = R_NilValue;
int i, errorOccurred, retVal=0;
// Convert the command line to SEXP
PROTECT(cmdSexp = Rf_allocVector(STRSXP, 1));
SET_STRING_ELT(cmdSexp, 0, Rf_mkChar(RScript.toLocal8Bit().data()));
cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue));
switch (status){
case PARSE_OK: {
// Loop is needed here as EXPSEXP might be of length > 1
for(i = 0; ((i < Rf_length(cmdexpr)) && (retVal==0)); i++){
R_tryEval(VECTOR_ELT(cmdexpr, i), R_GlobalEnv, &errorOccurred);
if (errorOccurred) {
// Interrupt process.
qDebug() << "Error occured" ;
retVal = -1;
}
}
break ;
}
default: {
qDebug() << "Incorrect R command" ;
break;
}
}
return 0;
}
如果R不是ggplot,则与R的通信可以正常工作。例如,如果我替换
RScript += "ggplot(data=df1,aes(x=id,y=notes))+geom_line() \n" ;
使用:
RScript += "plot(3) \n";
然后工作正常,使用所需的图创建一个png文件。 使用ggplot,此代码可以正常运行。不触发qDebug()消息。甚至会创建png文件(这意味着对png()的调用已正确执行)。但是文件为空。
这不仅是png()和ggplot()的组合,还是我的虚拟数据的问题,因为如果我只是在R控制台中启动以下R脚本,则会得到预期的结果(文件已创建并包含该图):
library("ggplot2")
id<-c(1,2,3,4,5)
names<-c("A","B","C","D","E")
notes<-c(12,20,13,15,10)
df1<-data.frame(id,names,notes)
png("C:/Users/Evain/Desktop/tests/testggplot.png", width=480, height=480, res=72)
ggplot(data=df1,aes(x=id,y=notes))+geom_line()
dev.off()
注意:我在Windows 10上,使用R3.4.3。 值得注意的是,png()方法在Linux上的行为略有不同。对于Windows,即使必须保留为空,也会在调用png()时创建文件。对于Linux,如果未写任何文件,则不会创建该文件。
如果png文件已经存在,它也会被替换为一个空文件。那就是我们在单独调用png()时应该期望的。只是没有将ggplot添加到其中。
感觉就像将R_tryEval()与png()结合使用一样不错。将png()与ggplot结合使用可以很好地工作,但是将R_tryEval()与png()和ggplot()结合使用则不能。有什么想法吗?