RcppArmadillo和arma命名空间

9

我之前在R中有经验,但对C++完全是新手。我使用RcppArmadillo编写了一些函数,并对其易用性和速度感到非常热情。现在,我想将这些函数转换为包,使用函数RcppArmadillo.package.skeleton()

只要在每个Armadillo对象(mat、colvec等)之前显式使用arma::前缀,就可以正常工作。然而,如果我在cpp文件开头放置using namespace arma;,并省略之后的arma::,我无法加载新创建的包,并获得大量错误,表明Armadillo命名空间未被识别。

任何关于如何解决此问题的帮助/建议都将不胜感激。谢谢,

Fabian

PS:我在Windows 7和Ubuntu 12.04上尝试了以上方法,每种情况下使用的是R 3.0.2和RcppArmadillo_0.4.000.4。

PS2:附加的cpp文件(松散地遵循http://gallery.rcpp.org/articles/simulate-multivariate-normal/)说明了我的观点。如果我通过sourceCpp(来自Rcpp包)将其源代码引入R中,则可以正常工作,但是当我尝试将其包含在新包中时,会出现上述问题。

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
colvec mvndrawC(colvec mu, mat sig) {

double k = mu.size();
colvec aux = as<colvec>(rnorm(k));
mat csig = chol(sig).t();
colvec out = mu + csig*aux;
return(out);

}

编辑:细节

以下是我执行以下操作时收到的错误输出:

  1. 运行命令RcppArmadillo.package.skeleton("test2"),从而为新包“test2”创建文件夹
  2. 将上述代码粘贴到.cpp文件中,并将其复制到新的test2/src文件夹中
  3. 尝试通过从devtools包调用load_all("test2")来加载新的test2

错误消息(在Rstudio中)

Loading test2
Re-compiling test2
'/usr/lib/R/bin/R' --vanilla CMD INSTALL '/home/fabian/test2' --library='/tmp    
/RtmplfAET0'  \
--no-R --no-data --no-help --no-demo --no-inst --no-docs --no-exec --no-multiarch  \
--no-test-load --preclean 

* installing *source* package 'test2' ...
** libs
g++ -I/usr/share/R/include -DNDEBUG   -I"/home/fabian/R/x86_64-pc-linux-gnu-library   
/3.0/Rcpp/include" -I"/home/fabian/R/x86_64-pc-linux-gnu-library/3.0/RcppArmadillo  
/include"  -UNDEBUG -Wall -pedantic -g -O0 -fpic  -O3 -pipe  -g  -c RcppExports.cpp -o 
RcppExports.o
RcppExports.cpp:10:1: error: 'colvec' does not name a type
RcppExports.cpp: In function 'SEXPREC* test2_mvndrawC(SEXP, SEXP)':
RcppExports.cpp:16:40: error: 'colvec' was not declared in this scope
RcppExports.cpp:16:40: note: suggested alternative:
/home/fabian/R/x86_64-pc-linux-gnu-library/3.0/RcppArmadillo/include/armadillo_bits   
/typedef_mat.hpp:65:22: note:   'arma::colvec'
RcppExports.cpp:16:47: error: template argument 1 is invalid
RcppExports.cpp:16:55: error: expected initializer before 'mu'
RcppExports.cpp:17:40: error: 'mat' was not declared in this scope
RcppExports.cpp:17:40: note: suggested alternative:
/home/fabian/R/x86_64-pc-linux-gnu-library/3.0/RcppArmadillo/include/armadillo_bits   
/typedef_mat.hpp:63:22: note:   'arma::mat'
RcppExports.cpp:17:44: error: template argument 1 is invalid
RcppExports.cpp:17:52: error: expected initializer before 'sig'
RcppExports.cpp:18:16: error: expected ';' before '__result'
RcppExports.cpp:19:9: error: '__result' was not declared in this scope
make: *** [RcppExports.o] Error 1
ERROR: compilation failed for package 'test2'
* removing '/tmp/RtmplfAET0/test2'
Error: Command failed (1)
In addition: Warning message:
The following packages are referenced using Rcpp::depends attributes however are  
not listed in the Depends and LinkingTo fields of the package DESCRIPTION file: 
RcppArmadillo 
PS3: 如果我在文件开头删除 // [[Rcpp... 这一行(但是这样就不能通过 sourceCpp 来源文件),最后的警告信息就会消失。

“不要担心信息不足,你的程序包应该无论如何都能加载。但如果有疑问,只需在前面加上 arma:: …” - Dirk Eddelbuettel
确实。尤其是在编译器错误消息通常很晦涩而且冗长的情况下,将它们发布出来仍然非常有帮助。 - Kevin Ushey
谢谢您的帖子,非常迅速!我编辑了问题以包含更多细节。 - Fabian
1个回答

8
我认为这是因为Rcpp属性将你创建的C++源文件编译成时,没有将using namespace arma;语句复制到其中。
这很棘手,因为不同的文件可能使用不同的命名空间,因此属性解析器无法将所有using namespace ...语句都复制到中,它只会默认使用Rcpp命名空间。如果我们随意地将所有的using namespace语句都复制到中,肯定会出现冲突。
总之,解决方法要么是显式地添加arma::前缀,要么是修改RcppExports.cpp文件,在顶部添加using namespace arma;(但是每次调用compileAttributes()后都必须这样做)。

2
哦,好的直觉。那是很有道理的。就我而言,在我的代码中使用显式的 arma:: - Dirk Eddelbuettel
8
否则,您可以在inst/include/test2.h中使用use namespace arma;,这将由compileAttribute自动#include - Romain Francois
感谢您的提示,以及首先提供Rcpp和RcppArmadillo!它们真正提高了R在我当前工作(贝叶斯时间序列模型的MCMC采样)中的吸引力。 - Fabian

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