我使用sourceCpp()
包中的Rcpp
来构建一个C ++文件并从R调用它。它似乎生成一个临时目录,它写入它编译的源代码,但它删除后的目录构建代码。我想访问它正在编译的确切文件,以便我可以在调试器中看到它。如何阻止sourceCpp()
删除它编译的文件?
答案 0 :(得分:3)
正如Dirk所说 - 认真,只需使用包。您在sourceCpp
之上开发的任何其他工作流程都可能不够/令人烦恼。
也就是说,Rcpp
不会自动删除生成源文件的目录。查看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:
输出并从那里开始。
但严重的是,只需制作一个包裹。
答案 1 :(得分:2)
由于未回答此问题,因此仍然是我的Google的第一个热门内容,因此请重新激活它。
我在文件f1.cpp
中保存了R函数的C版本。我(和操作员)想要的是sourceCpp("f1.cpp")
的结果,即文件f1.so
隐藏在通过函数cacheDir
的参数sourceCpp
定义的临时文件夹中。
但是,如果我将cacheDir=/my/path
设置为自己选择的导演,则仍然会创建临时目录,并且结果不会保存为/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 *)。我看不出“包装”是如何解决这个问题的。
答案 2 :(得分:1)
在进行学术研究时,我也喜欢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
文件。
答案 3 :(得分:0)
请参阅Rcpp属性小插图,了解如何从一次性文件转换为实验和探索(通过sourceCpp()
编译到组织文件 - 使用相同的技术 - 以R喜欢的方式:作为包裹。
这并不难,Rcpp Attributes会帮助你,你会在适当的时候看到优势。您可以从Rcpp.package.skeleton()
开始(请参阅其帮助页面)或从现有软件包中复制。
(另外,sourceCpp()
使用的临时目录与您拨打sourceCpp()
时所使用的R会话所使用的临时目录相同。我们不会进一步混淆。)