编译R包时调用Fortran 77 BLAS的dgemv函数出现参数数量不匹配错误
编译R包时调用Fortran 77 BLAS的dgemv函数出现参数数量不匹配错误
问题描述
我有一个用了好几年的R包,最近编译时突然遇到之前没见过的错误,特别是Fortran BLAS库的函数参数好像变多了。比如dgemv以前是11个参数,现在居然要求12个,编译报错说参数不够:
matrix.c:44:83: error: too few arguments to function call, expected 12, have 11 F77_CALL(dgemv)(transa, &nrx, &ncx, &alpha, x, &nrx, y, &ncy, &beta, z, &ncy);
我找不到这些新函数的文档,完全卡壳了。
代码是C写的,调用Fortran 77的dgemv做矩阵乘向量,下面是最小可复现示例:
C文件代码
#include <R.h> #include <Rinternals.h> #include <math.h> #include <R_ext/Applic.h> /* array.c says need for dgemm */ #include <R_ext/Lapack.h> /* array.c says need for dgemm */ /* following copied from array.c */ void matprod(double *x, int nrx, int ncx, double *y, int nry, int ncy, double *z, double alpha, double beta) { char *transa = "N"; F77_CALL(dgemv)(transa, &nrx, &ncx, &alpha, x, &nrx, y, &ncy, &beta, z, &ncy); }
R文件调用函数
mp <- function (x, y) { ## get dimensions dX <- dim(x) ly <- length(y) ## set up output z <- numeric(dX[1]) ## perform the matrix multiplication matprod(as.numeric(x), as.integer(dX[1]), as.integer(dX[2]), as.numeric(y), as.integer(ly), 1L, as.numeric(z), 1.0, 0.0) return(z) }
完整编译错误信息
── R CMD INSTALL ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ─ installing *source* package ‘testMWE’ ... ** using staged installation ** libs using C compiler: ‘Apple clang version 12.0.5 (clang-1205.0.22.9)’ using C++ compiler: ‘Apple clang version 12.0.5 (clang-1205.0.22.9)’ using SDK: ‘MacOSX11.3.sdk’ clang++ -arch x86_64 -std=gnu++17 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I'/Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/library/Rcpp/include' -I/opt/R/x86_64/include -fPIC -falign-functions=64 -Wall -g -O2 -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c RcppExports.cpp -o RcppExports.o clang -arch x86_64 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I'/Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/library/Rcpp/include' -I/opt/R/x86_64/include -fPIC -falign-functions=64 -Wall -g -O2 -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c testMWE.c -o testMWE.o testMWE.c:13:79: error: too few arguments to function call, expected 12, have 11 F77_CALL(dgemv)(transa, &nrx, &ncx, &alpha, x, &nrx, y, &ncy, &beta, z, &ncy); ~~~~~~~~~~~~~~~ ^ /Library/Frameworks/R.framework/Resources/include/R_ext/BLAS.h:107:1: note: 'dgemv_' declared here F77_NAME(dgemv)(const char *trans, const int *m, const int *n, ^ /Library/Frameworks/R.framework/Resources/include/R_ext/RS.h:81:24: note: expanded from macro 'F77_NAME' #define F77_NAME(x) F77_CALL(x) ^ /Library/Frameworks/R.framework/Resources/include/R_ext/RS.h:77:22: note: expanded from macro 'F77_CALL' # define F77_CALL(x) x ## _ ^ <scratch space>:83:1: note: expanded from here dgemv_ ^ 1 error generated. make: *** [testMWE.o] Error 1 ERROR: compilation failed for package ‘testMWE’ ─ removing ‘/private/var/folders/hy/gbflvvdd5935l261dv4gtf900000gn/T/RtmpVM5ny2/devtools_install_b83f5e2c276a/testMWE’ Error in `(function (command = NULL, args = character(), error_on_status = TRUE, …`: ! System command 'R' failed --- Exit status: 1 stdout & stderr: <printed> ---
系统信息
- Mac running Sonoma 14.6.1
- RStudio Version 2024.09.0+375 (2024.09.0+375)
我试过找BLAS函数的文档,也在电脑上找新函数,都没结果,可能我猜的原因不对?
解决方案及分析
问题根源
其实不是BLAS的dgemv本身参数变多了,而是R在新版本中(尤其是4.3.x及以后)对BLAS接口的封装做了调整——新增了一个用于传递Fortran字符串长度的参数。Fortran 77的字符串需要显式传递长度,旧版本的R封装可能帮你隐式处理了,但现在要求用户显式传入这个参数,这就是报错说需要12个参数的原因。
修复代码
你只需要在调用dgemv的时候,在transa参数后面加上它的长度即可。因为transa是"N",长度是1,有两种修改方式:
方式1:定义变量传递长度
void matprod(double *x, int nrx, int ncx, double *y, int nry, int ncy, double *z, double alpha, double beta) { char *transa = "N"; int trans_len = 1; // 新增:定义字符串长度变量 F77_CALL(dgemv)(transa, &trans_len, &nrx, &ncx, &alpha, x, &nrx, y, &ncy, &beta, z, &ncy); }
方式2:用复合字面量直接传递(C99及以后支持)
void matprod(double *x, int nrx, int ncx, double *y, int nry, int ncy, double *z, double alpha, double beta) { char *transa = "N"; F77_CALL(dgemv)(transa, &(int){1}, &nrx, &ncx, &alpha, x, &nrx, y, &ncy, &beta, z, &ncy); }
验证与后续建议
修改完代码后重新编译,应该就能顺利通过了。如果你不确定其他BLAS函数的参数变化,可以直接查看R安装目录下的R_ext/BLAS.h文件,里面有所有BLAS函数的最新声明,能帮你快速核对参数列表。
备注:内容来源于stack exchange,提问作者rje42
相关产品推荐
相关产品推荐

