【问题标题】:R package that links to external C library链接到外部 C 库的 R 包
【发布时间】:2012-09-08 04:59:37
【问题描述】:

我有一些使用igraph 库的c 代码。我想在它周围放一个 R 包装器并将其作为 R 包发送给 CRAN。

igraph 在 CRAN 上已经有一个 R 端口,所以我的 R 包 'foo' 依赖于 R 的 igraph 是有意义的。由于 foo 使用自己的依赖于 C igraph 的 C 代码,我如何将我的 C 函数链接到原始 igraph 库?我读过这是在一个名为 Makevars 的文件中完成的,但是链接到外部库非常麻烦。

如果这是不可能的,最好只复制整个 igraph 源代码并将整个内容放入我的 /src 目录中吗? R igraph 包已经有一个名为 Makevars 的文件,但我不明白所有 c 文件是如何构建的——通常在我的 Makefile 中我有类似 gcc(一些 .c 源文件列表)-o 之类的东西,但 Makevar 只包含

PKG_CFLAGS=-DUSING_R -I. -Ics -Iglpk -Iglpk/amd -Iglpk/colamd \
-g -O2 -I/usr/include/libxml2 -g -O2 -I/usr/include/libxml2 -DNDEBUG \
-DPACKAGE_VERSION=\"0.6\" -DINTERNAL_ARPACK \
-DIGRAPH_THREAD_LOCAL=/**/
PKG_CXXFLAGS= -DUSING_R -DIGRAPH_THREAD_LOCAL=/**/ -DNDEBUG
PKG_LIBS=-lxml2 -lz -lpthread -licucore -lm -lgmp  $(FLIBS) $(LAPACK_LIBS) $(BLAS_LIBS)

all: $(SHLIB)

并且没有其他 Makefile。总而言之,如何将 C 代码放入依赖于另一个 C 库的 R 包中,以及如何编写相应的 Makevars(或 Makefile)来合并 C 函数?

here 发布了一个较早的问题,但似乎只是链接到帮助编写您自己的不依赖于任何东西的 C 代码。

【问题讨论】:

  • 我认为目前这不可能以干净和便携的方式实现。
  • 这里只想提一下,复制整个 igraph 源代码也不是那么容易,因为它依赖于一些外部库,例如libxml2,GMP。我实际上与原始海报处于相同的情况,使用 GLPK 库/包。 igraph 现在包含 GLPK 的副本。

标签: c r graph linker igraph


【解决方案1】:

这里有几个问题:

  1. 包“foo”能否可靠地链接到包“bar”?正如 Gabor 在他之前的评论中暗示的那样,在第 5.8 节“链接到其他包”的开头的“编写 R 扩展”说“不,一般不”。

  2. 能否将 C 源代码放入包中以构建依赖于另一个库的包:可以,当然,CRAN 上的许多包都可以这样做。例如,根据 GSL、JPEG/TIFF 图形库、XML 或……选择一个包示例。您可以研究这些资源。这并非易事,但如果您研究了这些包,您应该可以了解编写 R 扩展中的文档以及此处相关问题的其他答案。

【讨论】:

    【解决方案2】:

    我对“编写 R 扩展”的阅读略有不同。第 5.8.1 节(处理类 unix 的操作系统)的第 1 段说,链接到 shared 库是可能的,但不可移植或不推荐。第 2 段说 static 库是可以的(该段开头的 'This' 令人困惑;它指的是什么?)因为 packA 提供的静态库可以由 packB 发现时 packB安装,然后合并到动态库中。这要求 packA 提供一个静态库,因此 packA 意识到它的作用就是这样做;许多包会认为它们的角色是为它们所包装的库的功能子集提供一个 R 接口,并提供一个链接到其自己包中的共享库的共享对象。

    一个例子是 Bioconductor 中的 Rsamtools 包,它创建了 samtools 库的静态版本,并为想要访问静态库的包提供了(棘手的)机制(vignette 提供了一个事物的依赖包视图)。提供静态库PKG_LIBS="-l$(PKGB_PATH)/libpackB.a" 的绝对路径很重要,以避免静态链接到系统提供的同一个库(带有packA 提供的标头)。

    @DirkEddelbuettel 几乎可以肯定自己已经走上了这条路,并且会指出我的错误。我同意他在下面的评论,即使用静态库是次优的(主要从内存消耗的角度来看?),但要选择避免第 5.8.1 段中提到的可移植性原因。

    【讨论】:

    • 并非如此。我不喜欢静态库(在 Unix 上,我们可以做得更好),而 Rcpp 等人所做的是不同的:他们自己构建了一个经典库,其他人链接到 - 而不是使用 R 构建的库。感觉我担心手册是正确的。但是,如果您想使用静态库强制执行操作,那么您所描述的内容是正确的——RInside 也是如此(至少在 Windows 上)。
    • @DirkEddelbuettel 你能详细说明“经典库”吗? Writing R Extensions 中的保留似乎是在运行时找到正确的库?
    • a) 编写 R 扩展只谈论 R,这是可以理解的。一个包 foo 得到一个文件 libs/foo.so。你不能链接到那个。然而,R 可以通过 dlopen 等打开它。 b) 我所谓的“经典”库通常称为 libfoo.so,您可以通过 -lfoo 链接它。
    • @DirkEddelbuettel 但我认为 R-exts 的重点是 -lfoo 要求 libfoo.so 在运行时可发现,它未安装在标准位置,因此不可发现(通常,当然,即使几乎每个人都会使用可以配置为在链接时记录 libfoo.so 位置的编译器)?
    • 没有 R 包提供 libfoo,他们所做的只是 libs/foo.so --- 目录 libs 中的文件 foo.so。不可发现是与运行时动态链接器有关的次要问题如果您谈论正常的可执行文件,对于 R 可加载包来说,情况完全不同。但主要问题是: foo.so 不能被 gcc 等人使用。
    猜你喜欢
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    相关资源
    最近更新 更多