我试着做一个简单的R命令评估器。
我有以下代码:
Evaluator.h
void evaluate(const std::string &command);
extern "C" SEXP run_eval() {
evaluate("grDevices:::png(\"snapshot.png\")");
return R_NilValue;
}Evaluator.cpp
SEXP createSexp(const std::string &str, ScopeProtector *protector) {
SEXP result = Rf_allocVector(STRSXP, 1);
protector->add(result);
SET_STRING_ELT(result, 0, Rf_mkChar(str.c_str()));
return result;
}
SEXP createExpressionSexp(SEXP strSexp, ScopeProtector *protector) {
ParseStatus status;
SEXP result = R_ParseVector(strSexp, 1, &status, R_NilValue);
protector->add(result);
return result;
}
SEXP createExpressionSexp(const std::string &str, ScopeProtector *protector) {
return createExpressionSexp(createSexp(str, protector), protector);
}
SEXP evaluateExpression(SEXP exprSexp, ScopeProtector *protector) {
SEXP result = Rf_eval(exprSexp, R_GlobalEnv);
protector->add(result);
return result;
}
void evaluate(const std::string &command) {
ScopeProtector protector;
evaluateExpression(createExpressionSexp(command, &protector), &protector);
}ScopeProtector.h
class ScopeProtector: boost::noncopyable {
public:
ScopeProtector();
virtual ~ScopeProtector();
void add(SEXP sexp);
private:
class Impl;
const std::unique_ptr<Impl> pImpl;
};ScopeProtector.cpp
class ScopeProtector::Impl {
public:
Impl() : count(0) {
}
virtual ~Impl() {
if (count > 0) {
UNPROTECT(count);
}
}
void add(SEXP sexp) {
PROTECT(sexp);
count++;
}
private:
int count;
};
ScopeProtector::ScopeProtector() : pImpl(new Impl) {
}
ScopeProtector::~ScopeProtector() = default;
void ScopeProtector::add(SEXP sexp) {
pImpl->add(sexp);
}CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(REvaluator)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror")
include_directories("/usr/share/R/include")
set(
SOURCE_FILES
Evaluator.cpp Evaluator.h
ScopeProtector.cpp ScopeProtector.h
)
add_library(revaluator SHARED ${SOURCE_FILES})我试图通过执行以下命令来检查我的评估器:
> dyn.load("librevaluator.so")
> .Call("run_eval")
NULL
> dev.list()
NULL如您所见,没有任何png设备。你能告诉我问题出在哪里吗?
发布于 2015-11-27 16:42:25
我找到了解决办法。只需替换
SEXP result = Rf_eval(exprSexp, R_GlobalEnv);使用
SEXP result = Rf_eval(VECTOR_ELT(exprSexp, 0), R_GlobalEnv);发布于 2015-11-26 17:52:42
你看过Rcpp和它的Rcpp::Function()吗?
R> library(Rcpp)
R> dev.list()
NULL
R> cppFunction('void newDev(std::string filename) {
Rcpp::Function dn = Rcpp::Function("png");
dn(filename); }')
R> newDev("/tmp/foo.png")
R> dev.list()
png
2
R> 我们通常不建议从“在C++中自下而上”调用大量的R函数,但是对于像创建图形设备这样的八层设置问题来说,这是非常好的。
(注意,我缩进代码以适应这里的显示。cppFunction()是一行;它创建一个具有参数中定义的函数的共享库,并分配它--这样我们刚才创建的新的R调用方newDev就可以用来创建png设备)。
https://stackoverflow.com/questions/33940409
复制相似问题