繁体   English   中英

Rcpp:如何保存sourceCpp生成的文件?

[英]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

这是非常麻烦的,因为现在我必须这样做

  1. find和mv /my/path/asd/asd/sourceCpp_2.so /my/path/f1.so
  2. 将相当复杂的行添加到R脚本中,其中最终将使用函数的C版本:
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)
  1. 最后,我可以将定义良好的/my/path及其所有内容添加到我正在处理的项目中(例如git *)。

我不知道“制作一个包”是如何回答这个问题的。

请参阅Rcpp属性小插图,了解如何从一次性文件转换为实验和探索(通过sourceCpp()编译到组织文件 - 使用相同的技术 - 以R喜欢的方式:作为包。

这并不难,Rcpp Attributes可以帮助您,您将在适当的时候看到优势。 您可以通过Rcpp.package.skeleton() (请参阅其帮助页面)或从现有包中复制。

(另外, sourceCpp()使用的临时目录与调用sourceCpp()时所使用的R会话使用的临时目录相同。我们不会进一步混淆。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM