3

我认为这个答案有点复杂,因为它涉及到几件事。

我想用 R 进行高性能计算,尤其是图形(网络)。作为 R 包igraph非常好。但是 R 很慢,所以我想用 C++(可能是 C)编写计算量大的例程。我看了一下igraph C 库,发现使用起来有点乱。我还查看了Boost Graph Library,我读到它很难学习。所以我最终找到了Lemon Graph Library。它在 C++ 中,看起来非常好用。

所以我按照官方页面的推荐安装了Lemon Graph Library。然后使用Rcpp内联包,我管理自己从 R 运行 Lemon Graph C++ 代码。在这里,我详细写下我所做的。但基本上我把这个:

   inc <- '
           #include <lemon/list_graph.h>
           using namespace lemon ;
           '


   src <- '
          int xx = Rcpp::as<int>(x);

          int res = xx + 1;

          ListDigraph g;

          ListDigraph::Node u = g.addNode();
          ListDigraph::Node v = g.addNode();
          ListDigraph::Arc  a = g.addArc(u, v);

          int i = countNodes(g);
          int j = countArcs(g);

          Rprintf("num nodes is %d , and num edges is %d \\n",i,j);

          return Rcpp::wrap(res);
          '

       fun <- cxxfunction( signature(x="numeric"), body=src,include=inc, plugin="Rcpp")

在 myexample_inline.R 文件中,然后运行 ​​R 控制台并写入:

> library("inline")
> library("Rcpp")
> source("myexample_inline.R")
> fun(1)
num nodes is 2 , and num edges is 1 
[1] 2

所以它有效!但现在我有以下问题。如果我创建一个 C++ 函数(比如 double func1(g)),例如计算某个 Lemon 图形对象的某些属性。我如何从内联代码中调用该函数?我必须将 func1() 作为模板函数并将其放在 cxxfunction() 的包含字段中吗?

基本上:我不知道如何从另一个也在 R 中内联的 C++ 函数调用在 R 中内联的 C++ 函数。这可能吗?还有另一种不使用内联代码的方法吗?

也许我可以使用Rcpp 模块来做到这一点,但我无法(仍然)弄清楚如何做到这一点。我在使模块工作时遇到问题。我会继续尝试这个,但也许我可以从这里得到一些提示。

我还考虑过开发(我的第一个)包的可能性。但是我遇到了 Lemon Graph C++ 代码以这种方式调用标题的问题(例如):

#include <iostream>
#include <lemon/list_graph.h>

所以这意味着(至少我相信这一点)我无法避免安装 Lemon Graph Library。如果我想制作 Lemon Graph Library 的 R 包,我必须再次“重写”所有代码!!!所以这不是我的主要选择。

此致

4

2 回答 2

2

我已经成功解决了这个问题。在这里,您可以找到有关我所做工作的详细说明。也许,这对这里的大多数人来说是微不足道的,但对于与我处于同一位置的人来说,这可能是一个很好的起点。我将在这里发布我所做的简历。

首先,我安装了 Lemon Graph (C++) Library (LGL)。我刚刚从它的主页(从这里)下载了 LGL。然后我继续:

$ tar xvzf lemon-1.2.tar.gz
$ cd lemon-1.2
$ ./configure
$ make
$ make check    # This is optional, but recommended. It runs a bunch of tests.
$ sudo make install

然后检查它是否有效。所以在一个名为 mycode.cc 的文件中,我放了:

#include <iostream>
#include <lemon/list_graph.h>

using namespace lemon;
using namespace std;

int main()
{
  ListDigraph g;

  ListDigraph::Node u = g.addNode();
  ListDigraph::Node v = g.addNode();
  ListDigraph::Arc  a = g.addArc(u, v);

  cout << "Hello World! This is LEMON library here." << endl;
  cout << "We have a directed graph with " << countNodes(g) << " nodes "
       << "and " << countArcs(g) << " arc." << endl;

  return 0;
}

然后我编译并运行它:

$ g++ -O2 mycode.cc -lemon
... BLA BLA BLA ... 
$./a.out
Hello World! This is LEMON library here.
We have a directed graph with 2 nodes and 1 arc.

所以它有效。现在,想法是通过 Rcpp 将该代码集成到 R 中。因此,在某个目录中,我打开了一个 R 控制台,然后执行以下操作:

> require("Rcpp")
Loading required package: Rcpp
> Rcpp.package.skeleton("pkgwithlgl")
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './pkgwithlgl/Read-and-delete-me'.

Adding Rcpp settings
 >> added Depends: Rcpp
 >> added LinkingTo: Rcpp
 >> added useDynLib directive to NAMESPACE
 >> added Makevars file with Rcpp settings
 >> added Makevars.win file with Rcpp settings
 >> added example header file using Rcpp classes
 >> added example src file using Rcpp classes
 >> added example R file calling the C++ example
 >> added Rd file for rcpp_hello_world

因此,通过这种方式,我刚刚创建了一个新的基于 Rcpp 的源包,名为 pkgwithlgl。现在在pkgwithlgl目录(这是我要修改和安装的包的源)内有一个名为src的目录。里面有包含包的 C++ 代码的文件。特别是有一个名为 *rcpp_hello_world.cpp* 的文件,其中包含:

#include "rcpp_hello_world.h"

SEXP rcpp_hello_world(){
   using namespace Rcpp ;

   CharacterVector x = CharacterVector::create( "foo", "bar" )  ;
   NumericVector y   = NumericVector::create( 0.0, 1.0 ) ;
   List z            = List::create( x, y ) ;

   return z ;
}

现在,我对其进行修改,使其变为:

#include "rcpp_hello_world.h"
#include <lemon/list_graph.h>
using namespace lemon ;

SEXP rcpp_hello_world(){
    using namespace Rcpp ;

    int res = 1;

    ListDigraph g;

    ListDigraph::Node u = g.addNode();
    ListDigraph::Node v = g.addNode();
    ListDigraph::Arc  a = g.addArc(u, v);

    int i = countNodes(g);
    int j = countArcs(g);

    Rprintf("num nodes is %d , and num edges is %d \n",i,j);

    return wrap(res) ;
}

然后,从我写的源包容器目录中的 linux 控制台:

$ R CMD INSTALL pkgwithlgl

返回:

* installing to library ‘/home/juan/R/x86_64-pc-linux-gnu-library/2.12’
* installing *source* package ‘pkgwithlgl’ ...
** libs
g++ -I/usr/share/R/include   -I"/usr/local/lib/R/site-library/Rcpp/include"   -fpic  -O3     -pipe  -g -c rcpp_hello_world.cpp -o rcpp_hello_world.o
g++ -shared -o pkgwithlgl.so rcpp_hello_world.o -L/usr/local/lib/R/site-library/Rcpp/lib     -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR
installing to /home/juan/R/x86_64-pc-linux-gnu-library/2.12/pkgwithlgl/libs
** R
** preparing package for lazy loading
** help
Warning:     /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work-    space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl-    package.Rd:32: All text must be in a section
Warning:     /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work-    space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl-   package.Rd:33: All text must be in a section
*** installing help indices
  converting help for package ‘pkgwithlgl’
    finding HTML links ... done
    pkgwithlgl-package                      html  
    rcpp_hello_world                        html  
** building package indices ...
** testing if installed package can be loaded

* DONE (pkgwithlgl)    

所以安装了包(警告与我没有以正确的方式填写 .Rd 文件有关,即包含有关包的帮助的文件)。我打开一个 R 控制台并写:

> require("pkgwithlgl")
Loading required package: pkgwithlgl
Loading required package: Rcpp
> rcpp_hello_world()
num nodes is 2 , and num edges is 1
[1] 1

所以它有效!就这些。

但是,嘿!如果我构建这个包并将其上传到(例如)CRAN 会发生什么(我不会这样做)。如果有人从 CRAN 安装这个软件包,它对他有用吗?就算不安装LGL包?

此致

于 2011-02-11T18:34:01.783 回答
1

您好,感谢您对Rcpp的关注。

要在不同的库函数之间绑定调用,您可能需要考虑构建一个包。现在有 20 个使用 Rcpp 的包,列在 CRAN 的 Rcpp 页面上,因此您可以从中复制示例。乍一看,。这与编写普通程序没有什么不同,Rcpp 只是帮助您将其导入 R。

如果您有更多问题,请随时将它们带到rcpp-devel列表中。

于 2011-02-07T01:38:41.910 回答