[英]Rcpp: how to keep files generated by sourceCpp?
我用sourceCpp()
从Rcpp
包建一个C ++文件,并从R.调用它似乎产生在那里将其写入编译源的临时目录,但它构建代码后删除该目录。 我想访问它正在编译的确切文件,以便我可以在调试器中看到它。 如何防止sourceCpp()
删除它编译的文件?
正如Dirk所说 - 严肃地说,只需使用包裹 。 您在sourceCpp
之上开发的任何其他工作流程可能不够/烦恼使用。
也就是说, Rcpp
不会自动删除生成源文件的目录。 查看sourceCpp(..., verbose = TRUE)
的输出sourceCpp(..., verbose = TRUE)
:
> sourceCpp("~/scratch/save-source-cpp.cpp", verbose = TRUE)
Generated extern "C" functions
--------------------------------------------------------
#include <Rcpp.h>
RcppExport SEXP sourceCpp_2047_timesTwo(SEXP xSEXP) {
BEGIN_RCPP
SEXP __sexp_result;
{
Rcpp::RNGScope __rngScope;
Rcpp::traits::input_parameter< int >::type x(xSEXP );
int __result = timesTwo(x);
PROTECT(__sexp_result = Rcpp::wrap(__result));
}
UNPROTECT(1);
return __sexp_result;
END_RCPP
}
Generated R functions
-------------------------------------------------------
`.sourceCpp_2047_DLLInfo` <- dyn.load('/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T//RtmppARq3j/sourcecpp_1b612a59c474/sourceCpp_85891.so')
timesTwo <- Rcpp:::sourceCppFunction(function(x) {}, FALSE, `.sourceCpp_2047_DLLInfo`, 'sourceCpp_2047_timesTwo')
rm(`.sourceCpp_2047_DLLInfo`)
Building shared library
--------------------------------------------------------
DIR: /var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T//RtmppARq3j/sourcecpp_1b612a59c474
/Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB -o 'sourceCpp_85891.so' 'save-source-cpp.cpp'
clang++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG -I/usr/local/include -I/usr/local/include/freetype2 -I/opt/X11/include -I"/Users/kevin/Library/R/3.1/library/Rcpp/include" -fPIC -g -O3 -Wall -pedantic -c save-source-cpp.cpp -o save-source-cpp.o
clang++ -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/usr/local/lib -o sourceCpp_85891.so save-source-cpp.o -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
注意DIR:
行。 如果我看看里面有什么,我看到:
> list.files("/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T//RtmppARq3j/sourcecpp_1b612a59c474")
[1] "save-source-cpp.cpp" "save-source-cpp.cpp.R" "save-source-cpp.o" "sourceCpp_29322.so"
如果我读了(修改过的)cpp文件,我看到:
> cat(readLines("/var/folders/tm/5dt8p5s50x58br1k6wpqnwx00000gn/T//RtmppARq3j/sourcecpp_1b612a59c474/save-source-cpp.cpp"), sep = "\n")
#include <Rcpp.h>
using namespace Rcpp;
// Below is a simple example of exporting a C++ function to R. You can
// source this function into an R session using the Rcpp::sourceCpp
// function (or via the Source button on the editor toolbar)
// For more on using Rcpp click the Help button on the editor toolbar
// [[Rcpp::export]]
int timesTwo(int x) {
return x * 2;
}
#include <Rcpp.h>
RcppExport SEXP sourceCpp_2047_timesTwo(SEXP xSEXP) {
BEGIN_RCPP
SEXP __sexp_result;
{
Rcpp::RNGScope __rngScope;
Rcpp::traits::input_parameter< int >::type x(xSEXP );
int __result = timesTwo(x);
PROTECT(__sexp_result = Rcpp::wrap(__result));
}
UNPROTECT(1);
return __sexp_result;
END_RCPP
}
所以我们所做的就是使用可以理解常规函数接口的.Call
接口生成包装函数。
如果要在某处保存该文件,可以使用capture.output(sourceCpp(..., verbose = TRUE))
然后解析DIR:
输出并从那里开始。
但说真的,只需要打包。
在做学术研究时,我也喜欢sourceCpp
的灵活性。 在许多情况下,编写程序包对我们来说太多了。 我一直在使用sourceCpp
的以下包装器来保存共享库。
importCpp <- function(infile, output_dir="lib", rebuild=FALSE){
output_dir = ifelse(is.null(output_dir), ".", output_dir)
dir.create(output_dir, recursive=T, showWarnings=FALSE)
outfile = file.path(output_dir, paste0(infile, ".R"))
if (!file.exists(outfile) || file.info(infile)$mtime > file.info(outfile)$mtime || rebuild){
Rcpp::sourceCpp(infile, rebuild=rebuild)
context = .Call("sourceCppContext", PACKAGE = "Rcpp",
normalizePath(infile, winslash = "/"), code=NULL, 0L, .Platform)
scriptfile = file.path(context$buildDirectory, context$rSourceFilename)
content = readLines(scriptfile)
ext = .Platform$dynlib.ext
m = regexpr(paste0("(?<=dyn.load\\(').*", ext), content[1], perl=TRUE)
shlibfile = file.path(output_dir, paste0(infile, ext))
shlibfile0 = regmatches(content[1], m)
content[1] = sub(shlibfile0, shlibfile, content[1])
f = file(outfile, "w+")
writeLines(content, f)
close(f)
file.copy(shlibfile0, shlibfile, overwrite=TRUE)
}else{
source(outfile)
}
invisible(outfile)
}
要使用代码:
importCpp("foo.cpp")
如果文件未编译,则共享库和R文件foo.cpp.R
将复制到当前文件夹下的文件夹lib
。 但是,如果找到lib\\foo.cpp.R
,它将获取R文件。
另外,如果foo.cpp
被修改, importCpp
将重新编译的cpp
如果有必要的文件。
重新激活这个问题,因为它没有被回答,它仍然是我的谷歌第一次击中。
我有一个C版本的R函数保存在文件f1.cpp
。 我(和op)想要的是sourceCpp("f1.cpp")
,即文件f1.so
,它隐藏在通过函数sourceCpp
的参数cacheDir
定义的临时文件夹中。
但是,如果我将cacheDir=/my/path
设置为我选择的/my/path/sourceCpp-x86_64-pc-linux-gnu-1.0.1/sourcecpp_2db138ae3a0c/sourceCpp_2.so
,仍会创建临时目录,结果不会保存为/my/path/f1.so
而是保存为/my/path/sourceCpp-x86_64-pc-linux-gnu-1.0.1/sourcecpp_2db138ae3a0c/sourceCpp_2.so
。
这是非常麻烦的,因为现在我必须这样做
mv /my/path/asd/asd/sourceCpp_2.so /my/path/f1.so
f1 <- Rcpp:::sourceCppFunction(function(arg1, arg2) {},
isVoid=F, dll=dyn.load("my/path/f1.so"),
symbol='sourceCpp_1_f1') # from the generated file f1.cpp.R
res <- f1(arg1, arg2)
/my/path
及其所有内容添加到我正在处理的项目中(例如git *)。 我不知道“制作一个包”是如何回答这个问题的。
请参阅Rcpp属性小插图,了解如何从一次性文件转换为实验和探索(通过sourceCpp()
编译到组织文件 - 使用相同的技术 - 以R喜欢的方式:作为包。
这并不难,Rcpp Attributes可以帮助您,您将在适当的时候看到优势。 您可以通过Rcpp.package.skeleton()
(请参阅其帮助页面)或从现有包中复制。
(另外, sourceCpp()
使用的临时目录与调用sourceCpp()
时所使用的R会话使用的临时目录相同。我们不会进一步混淆。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.