首页 > 解决方案 > 如何使用 Makevars 链接到 RCPP 中已编译的外部共享库?

问题描述

我查看了多个地方,但没有找到一个简单的例子来解决我的问题。

我需要的是能够使用我拥有的多个 .so 文件(连同 .h 文件)。

一个简单的例子是:

我有以下文件:啊,a.cp​​p 函数 jeden - 这是我的 R 库 accessor.cpp,它向 R 公开来自外部库 libdwa.so 的函数 dwa。我有头文件 dwa.h 和这个库 libdwa.so。

只有当我将库文件 libdwa.so 放入目录'/usr/lib'(我使用 Debian)时,我才能管理构建二进制包(一切正常)。但这不是可分割的解决方案。

我应该在哪里放置库“dwa”文件(dwa.h 和 libdwa.so)以及在 Makevars 文件中添加哪些标志以获得可移植解决方案?

已添加摘要

我在这里总结了我的结果。我相信一些极其简单的例子在开始时很有用。

  1. 2个外部库放入inst

    /inst/include/dwa.h
    /inst/include/trzy.h
    /inst/jeden/libdwa.so
    /inst/jeden/libtrzy.so
    
  2. 配置文件/configure具有以下形式(test6 是包的名称):

    #!/bin/bash
    rpath=$(${R_HOME}/bin/Rscript -e 'cat(file.path(.libPaths()[1], "test6", "jeden"))') #'
    sed -e"s|@rpath@|"${rpath}"|" src/Makevars.in > src/Makevars
    
    exit 0
    
  3. 文件/src/Makevars.in具有以下形式:

    CXX_STD = CXX11
    
    PKG_CPPFLAGS = -I../inst/include/ -I.
    PKG_LIBS     = -ldwa -ltrzy -L../inst/jeden -Wl,-rpath,@rpath@
    
  4. /src/accessor.cpp将库函数暴露给 R

    #include <Rcpp.h>
    #include "../inst/include/dwa.h"
    #include "../inst/include/trzy.h"
    
    // [[Rcpp::export]]
    Rcpp::String r_dwa() {
      Rcpp::String res = dwa();.
      return res;
    }
    
    // [[Rcpp::export]]
    Rcpp::String r_trzy() {
      Rcpp::String res = trzy();.
      return res;
    }
    
  5. 纯 R 库 _/src/hello_world.cpp_ 也存在:

    #include <Rcpp.h>
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    String hello_world() {
      String hw = "Hello World";
      return hw ;
    }
    
  6. 最后/NAMESPACE文件:

    useDynLib("test6", .registration=TRUE)
    
    import("Rcpp")
    importFrom("utils", "object.size", "packageVersion")
    exportPattern("^[[:alpha:]]+")
    

构建代码包和二进制包是成功的,但只有代码包是有用的,因为二进制文件具有严格编写的库的路径。

标签: c++rcpp

解决方案


假设您有一个目录结构,例如

/opt/dwa/include/dwa.h
/opt/dwa/lib/libdwa.so

在这种情况下,您可以使用 is src/Makevars

PKG_CPPFLAGS = -I/opt/dwa/include
PKG_LIBS = -L/opt/dwa/lib -ldwa -Wl,-rpath,/opt/dwa/lib

当然,这仍然是不可移植的,因为库和头文件的路径是硬编码的。为了规避这一点,可以使用模板文件,例如src/Makevars.in

PKG_CPPFLAGS = @DWA_INC@
PKG_LIBS = @DWA_LIB@

并编写一个configure脚本来检查环境并src/Makevars根据发现进行创建。configure编写脚本有不同的策略。我通常使用autoconf,例如在RcppArrayFiredqmagic中。


推荐阅读