R和C++之间的通信

4
我有一个用C++编写的程序,该程序计算似然函数的值,这需要很多数据。我想从R中调用该函数以请求函数的值(在R中进行计算会花费太多时间,而且C++程序已经太长了,大约有150K行代码)。我可以通过使用`.c()`来请求一个值,但是C++应用程序随后终止,然后我必须重新启动它并重新加载所有数据。读取所有数据需要10-30秒,具体取决于似然函数模型和数据,因此我在思考是否有一种方法可以使C++应用程序保持活动状态,等待请求函数值,以便我不必将所有数据重新读入内存中。在C++应用程序中已经计算一个函数值需要大约半秒钟,这对于C++来说非常长。我正在考虑使用`pipe()`来完成这个任务,并请问您是否使用其他方法或者是否可以使用rcpp来完成此操作?我正在使用此功能测试R上的最小化算法。

6
可以考虑看一下 Rcpp?网址为 http://cran.r-project.org/web/packages/Rcpp/index.html。 - juba
管道看起来是一个可能的解决方案,或者也许是 TCP 服务器? - 4pie0
2
我觉得这个问题有点混乱,编辑可能会有所帮助。你要么在主C++函数中需要一些R功能——这就是RInside的用途——要么你有C++代码想要从R中调用——这就是Rcpp的优势。无论哪种情况,Rcpp代码都用于使数据传输变得容易。而且在任何一种情况下,它都是相同的过程,因此pipe()等不适用。除非你做了比你想要的更复杂的事情。 - Dirk Eddelbuettel
此外,如果您能够发布用于进行外部.C()调用的R代码,那将非常有帮助。 - mrip
我有一个主要的C++函数,但是这个主函数非常简单,我认为我可以使用Rcpp模块来搞定它。 - Gumeo
显示剩余4条评论
2个回答

7

忘掉.C,那很笨重。或许在Rcpp出现之前,使用.C来代替.Call或者.External是有意义的。但是现在有了我们投入的工作,我真的看不出再使用.C有什么意义了。只需使用.Call即可。

更好的是,借助属性(sourceCppcompileAttributes),你甚至不必再看到.Call,感觉就像在使用c++函数。

现在,如果我想要做一些保留状态的事情,我会使用一个模块。例如,您的应用程序是这个Test类。它具有方法do_somethingdo_something_else,并且它计算了这些方法被使用的次数:

#include <Rcpp.h>
using namespace Rcpp ;

class Test {
public:
    Test(): count(0){}

    void do_something(){
        // do whatever
        count++ ;
    }
    void do_something_else(){
        // do whatever
        count++ ;
    }

    int get_count(){
        return count ;
    }

private:
    int count ; 
} ;

到目前为止,这是标准的C++。现在,要使其可用于R,您需要创建一个模块,如下所示:

RCPP_MODULE(test){
    class_<Test>( "Test" )
        .constructor()
        .method( "do_something", &Test::do_something )
        .method( "do_something_else", &Test::do_something_else )

        .property( "count", &Test::get_count )
    ;
}

然后你可以直接使用它:

app <- new( Test )
app$count
app$do_something()
app$do_something()
app$do_something_else()
app$count

非常感谢您的回复,我认为我可以通过创建这样一个模块来解决这个问题! - Gumeo

1

这里有几个问题。

如何从R中调用C++代码?

正如其他评论者所指出的那样,Rcpp包提供了最好的接口。使用基本R中的.Call函数也是可能的,但不像Rcpp那样好用。

如何防止在R和C++之间反复传递数据?

你只需要稍微重构一下你的代码。在C++中重写一个包装程序,调用所有现有的C++程序,并从R中调用它。


1
.Call()函数是必需的,因为.C()接口受限,容易出错,不应该被使用--例如查看几个月前r-devel中Simon Urbanek的意见。 - Dirk Eddelbuettel
@DirkEddelbuettel,您能详细说明为什么.C()容易出错,或者发布一下Simon Urbanek在r-devel上的消息链接吗? - mrip
2
@mrip:这里有。R核心成员Simon Urbanek在r-devel上的发言:“像往常一样,我只能说不要使用.C()”。我把日期搞错了:这已经是在2012年了——时间飞逝,但仍有一些人认为他们应该使用.C()。这已经够糟糕了,但更糟糕的是,当他们把这种错误的想法强加给别人时。 - Dirk Eddelbuettel
谢谢。我问的原因是我有一些C代码,我用.C()调用它,但我没有注意到任何问题。我认为这并不是很糟糕——这是一个非常简单的C接口。 - mrip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接