微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何加载 C++ 模块并将编译标志作为 Rcpp 包编译的一部分?

如何解决如何加载 C++ 模块并将编译标志作为 Rcpp 包编译的一部分?

我正在使用 Rcpp 将 C++ 程序包装在 R 包中。我的 C++ 程序需要以下头文件

#include "htslib/sam.h"

在编译之前,我通常会在 Ubuntu 中加载以下模块:

htslib/1.11-GCC-9.3.0

我通常使用 GCC/9.3.0 在 Ubuntu 中使用以下标志编译 C++ 脚本:

g++ scriptname.cpp -Ihtslib -Lhtslib -lhts

由于我是通过 Rcpp 从 R 访问程序,所以我不知道如何加载 htslib 模块。当我尝试“清理并重建”包时,出现以下错误

Fatal error: htslib/sam.h: No such file or directory
    #include "htslib/sam.h"
                           ^
   compilation terminated.

我有两个问题:

  1. 从 C++ 源代码构建 R 包时如何加载 C++ 模块?

  2. 从 C++ 源代码构建 R 包时如何包含编译标志?

我创建了一个最小的头文件、.R 文件和 C++ 源脚本。该脚本打开一个 bam 文件输出读取的染色体名称和位置。这些文件并不代表我想要运行的实际程序(它太长且太复杂,无法包含在此处),但是当我尝试使用 Rcpp 构建包时会产生相同的错误

C++ 源文件

#include "htslib/sam.h"
#include <string>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <Rcpp.h>
#include "htslibBasics.h

void OpenBam(std::string command_string){
    // Stores filename and converts to character string
    const char * char_command;
    char_command = command_string.c_str();
    
    // Opens bam file
    samFile *fp = sam_open(char_command,"r");
    
    // Opens bam header
    bam_hdr_t *h = sam_hdr_read(fp);
    
    // Initialize an alignment
    bam1_t *b = bam_init1();
    
    while(sam_read1(fp,h,b) >= 0) {
        if (b->core.tid < 0){
            continue;
        }else{
            std::cout << h->target_name[b->core.tid] << "\t" << b->core.pos << "\t" << bam_endpos(b) << std::endl;
       }
    }
    
    /*
    * Destroy the alignment and header which have been read into the C++ program
    * and close the sam file.
    */
    bam_destroy1(b);
    bam_hdr_destroy(h);
    sam_close(fp);
}

文件

#ifndef OPEN_BAM
#define OPEN_BAM

//' Documentation
//' @param command_string Documentation
// [[Rcpp::export]]
void OpenBam(std::string command_string);

#endif // OPEN_BAM

R 文件

## usethis namespace: start
#' @useDynLib htslibBasics,.registration = TRUE
## usethis namespace: end
NULL
## usethis namespace: start
#' @importFrom Rcpp sourceCpp
## usethis namespace: end
NULL
#' Documentation
#' @export
OpenBam <- function(command_string) {
  .Call(`_htslibBasics_OpenBam`,command_string)
}

R 文件位于包的“R”目录中,而 C++ 脚本和头文件位于“src”目录中。

解决方法

我想通了:原来答案很简单。我粗略地关注了 Dirk Eddelbuettel 的小插图 (https://cloud.r-project.org/web/packages/Rcpp/vignettes/Rcpp-libraries.pdf),并结合了来自网络的大量信息。

在命令行中,我导航到系统上的 HTSlib 目录:

cd /sw/eb/sw/HTSlib/1.11-GCC-9.3.0/

接下来,我导航到包含 htslib 头文件的目录,并将它们移动到 R 包的 src/ 目录:

cd include/htslib
cp *.h /home/annabelperry/R/HTSlibBasics/src/

然后,我导航到我的 C++ 源文件并将标题 include "htslib/sam.h" 更改为 include "sam.h",因为我的 sam.h 文件不再在 htslib 目录中。

然后我导航到 HTSlib 库目录并将每个文件复制到我的 R 包外的一个目录中。 (注意:我尝试复制整个目录并移动它,但这导致了编辑访问问题)。

cd /sw/eb/sw/HTSlib/1.11-GCC-9.3.0/lib
cp libhts.a /home/annabelperry/R/lib/
cp libhts.so /home/annabelperry/R/lib/
cp libhts.so.1.11 /home/annabelperry/R/lib/
cp libhts.so.3 /home/annabelperry/R/lib/
cd pkgconfig
cp htslib.pc /home/annabelperry/R/lib/pkgconfig/

然后我在 src/ 目录中为我的 R 包创建了一个名为 Makevars 的文件并输入:

CXX_STD = CXX11
PKG_CXXFLAGS = -Ihtslib
PKG_LIBS = -L/home/annabelperry/R/lib -lhts -Wl,-rpath,/home/annabelperry/R/lib

-L 链接器标志给出了在其中查找库文件的目录,而 -l 链接器标志给出了库文件的基本名称。

当我尝试构建包时,我收到一条错误消息,指出找不到 libcrypto.so.10 库。我将此库从其原始目录 /usr/lib64 移至 /home/annabelperry/R/lib/ 目录以及我的其余库文件。

我还必须从我的源代码中删除所有 std::cout 调用,因为它们与 Rcpp 不兼容。

在此之后,我可以成功构建包。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?