向含Rcpp的R包添加Fortran子程序编译报错,求解决方法
问题:R包整合Fortran子程序编译失败
场景重现
原本可正常编译的R包,加入从网上找到的Fortran子程序后,运行devtools::document()时出现编译错误,提示addf_未声明。相关代码如下:
R文件夹代码
#' @export testfun<-function() { addc(1,2) + add_Fortran(1,2) } #' @useDynLib testpac addf #' @export add_Fortran <- function(x, y) { .Fortran(addf, x, y, numeric(1))[[3]] }
src文件夹代码
C++文件:
#include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] double addc(double x, double y) { return x*y; }
Fortran文件:
subroutine addf(x, y, answer) double precision x, y, answer answer = x + y end
错误信息
from 1mRcppExports.cpp:4: 1mRcppExports.cpp:28:34: 1;31merror: '1maddf_' was not declared in this scope 28 | {"addf", (DL_FUNC) &F77_NAME(1;31maddf), 3}, | 1;31m^~~~ 1mC:/R/include/R_ext/RS.h:104:25: 1;36mnote: in definition of macro '1mF77_CALL' 104 | # define F77_CALL(x) 1;36mx ## _ | 1;36m^ 1mRcppExports.cpp:28:25: 1;36mnote: in expansion of macro '1mF77_NAME' 28 | {"addf", (DL_FUNC) &1;36mF77_NAME(addf), 3}, | 1;36m^~~~~~~~ make: *** [C:/R/etc/x64/Makeconf:296: RcppExports.o] Error 1 ERROR: compilation failed for package 'testC'
解决方案
错误原因是C++编译器编译自动生成的RcppExports.cpp时,找不到Fortran子程序编译后的符号(addf_)。只需添加外部函数声明即可解决:
方法1:在C++代码中添加extern声明
在你的C++文件顶部添加以下代码,告诉编译器addf_是一个外部C风格函数:
extern "C" { void addf_(double* x, double* y, double* answer); }
修改后的C++文件如下:
#include <Rcpp.h> using namespace Rcpp; // 声明Fortran子程序的C接口 extern "C" { void addf_(double* x, double* y, double* answer); } // [[Rcpp::export]] double addc(double x, double y) { return x*y; }
方法2:用模块封装Fortran子程序
将Fortran代码改为模块形式,编译器会自动生成更清晰的接口,同时避免符号命名问题:
module add_module contains subroutine addf(x, y, answer) double precision x, y, answer answer = x + y end subroutine addf end module add_module
之后同样需要在C++代码中添加extern声明(符号名可能变为add_module_addf_,具体取决于编译器,可通过查看编译后的目标文件确认)。
验证修改
添加声明后,重新运行devtools::document()和devtools::install(),即可正常编译。
内容的提问来源于stack exchange,提问作者Wolfgang Rolke
相关产品推荐
相关产品推荐

