代码之家  ›  专栏  ›  技术社区  ›  ShanZhengYang

useDynLib()错误和compileAttributes不返回任何内容:将C库嵌入到R包中

  •  0
  • ShanZhengYang  · 技术社区  · 7 年前

    我有一个C包,它构建了一个具有多个参数标志的可执行文件。其中一个使用Makefile编译代码(我知道,对于R包,这需要更改),并创建一个可执行文件以通过运行

    $ ./codeName -f path/inputfile -o path/outputfile -p ## -s "type"

    我的目标是将此C包中使用的几个函数集成到R库中。我看了一些关于 github.com/cran 在编写R扩展时,它解释了如何使用 .Call() Makevars 为了从R调用C函数,我想避免类似瘟疫的情况。然而,这似乎需要用 SEXP 对象——所以我转向Rcpp(耶!)

    我创建包 Rcpp.package.skeleton("packageName")

    太棒了在R中,我执行以下操作:

    $ R
    > library(devtools)
    > build()  # works!
    > install() # works!
    > library(packageName)
    > rcpp_hello_world()
    ## expected output
    

    一切正常。然后我将我的C包添加到 /src . 然后我执行 Rcpp::compileAttributes() 在通过R的包根目录中,什么都不发生,也没有输出,这是意料之中的,因为我还没有更改C代码。

    我尝试使用上述命令安装: devtools::build() devtools::install() . 通过 Makefile

    ** R
    ** preparing package for lazy loading
    ** help
    *** installing help indices
    ** building package indices
    ** testing if installed package can be loaded
    Error in library.dynam(lib, package, package.lib) : 
      shared object ‘packageName.so’ not found
    Error: loading failed
    Execution halted'
    ERROR: loading failed
    

    嗯,这有点令人困惑,我不知道为什么会发生这种情况,但问题是 useDynLib("packageName") 在命名空间中。如果我删除它,C代码看起来是编译的,包通过 build/install 上面的命令。 rcpp_hello_world() 仍然有效。

    (1) 为什么会出现这种错误 ‘packageName.so’ not found 现在就出现,我能绕过它吗?

    (这个问题与Rcpp无关。)

    .c 文件我添加

    #include <Rcpp.h>
    using namespace Rcpp;
    

    到a *.c 文件和 //[[Rcpp::export]] 在我想要导入的函数之前。(我不确定这是否会奏效 *.c ,或在C头文件中。)

    接下来,我转到包根目录,打开R并尝试以下操作:

    $ R
    > library(Rcpp)
    > compileAttributes()
    

    运行时不会出错。但是,没有 RcppExports.R RcppExports.cpp 已生成。编译C代码也会导致无法找到的错误 #include <Rcpp.h> .

    (2) 为什么会这样 compileAttributes() Rcpp //[[Rcpp::导出]] 为了将这些C函数包装成R可用的格式。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Dirk is no longer here    7 年前

    这个函数叫什么?C代码?

    int fib(int n) { 
       if (n < 2) return n;
       return fib(n-1) + fib(n-2);
    }
    

    它作为C和C++代码传递。让我们称之为C代码。

    您可以通过Rcpp从R清楚地将其与以下调用者连接:

    // [[Rcpp::export]]
    int callFib(int n) {
       return fib(n);
    }
    

    把它们粘在一起 保存到C++文件中,以便Rcpp可以对其进行操作 (请参阅注释)您已经准备好了。

    R> library(Rcpp)
    R> sourceCpp("/tmp/ex.cpp")
    
    R> callFib(10)
    [1] 55
    R> 
    

    完整文件如下。

    #include <Rcpp.h>
    
    int fib(int n) { 
      if (n < 2) return n;
      return fib(n-1) + fib(n-2);
    }
    
    
    // [[Rcpp::export]]
    int callFib(int n) {
      return fib(n);
    }
    
    /*** R
    callFib(10)
    */