Linking error of R package with Rcpp: “undefined symbol: LAPACKE_dgels”
我正在创建一个R包" lapacker",以使用R API头文件" R_ext / Lapack.h"为R提供和使用的内部LAPACK库提供C接口(仅具有双精度和双复数)。源代码:
https://github.com/ypan1988/lapacker/
项目结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /lapacker /inst /include /lapacke.h /someother header files /R /zzz.R /src /lapacke_dgetrf.c /lapacke_dgetrf_work.c /loads of other utility functions provided by LAPACKE /rcpp_hello.cpp DESCRIPTION NAMESPACE |
在项目内部,我尝试了rcpp_hello.cpp文件中的测试功能(请注意,此示例来自https://www.netlib.org/lapack/lapacke.html#_calling_code_dgels_code):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | //'@export // [[Rcpp::export]] void example_lapacke_dgels() { double a[5][3] = {{1,1,1},{2,3,4},{3,5,2},{4,2,5},{5,4,3}}; double b[5][2] = {{-10,-3},{12,14},{14,12},{16,16},{18,16}}; lapack_int info,m,n,lda,ldb,nrhs; int i,j; m = 5; n = 3; nrhs = 2; lda = 3; ldb = 2; info = LAPACKE_dgels(LAPACK_ROW_MAJOR,'N',m,n,nrhs,*a,lda,*b,ldb); for(i=0;i<n;i++) { for(j=0;j<nrhs;j++) { printf("%lf",b[i][j]); } printf("\ "); } } |
整个程序包可以正确编译而没有错误,并且在R中给出正确的答案(可以找到符号LAPACKE_dgels):
1 2 3 4 | > example_lapacke_dgels() 2.000000 1.000000 1.000000 1.000000 1.000000 2.000000 |
但是,当我创建一个单独的C文件时,请说出具有完全相同功能的demo3.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include <Rcpp.h> #include <lapacke.h> // [[Rcpp::depends(lapacker)]] // [[Rcpp::export]] void lapacke_dgels_test() { double a[5][3] = {{1,1,1},{2,3,4},{3,5,2},{4,2,5},{5,4,3}}; double b[5][2] = {{-10,-3},{12,14},{14,12},{16,16},{18,16}}; lapack_int info,m,n,lda,ldb,nrhs; int i,j; m = 5; n = 3; nrhs = 2; lda = 3; ldb = 2; info = LAPACKE_dgels(LAPACK_ROW_MAJOR,'N',m,n,nrhs,*a,lda,*b,ldb); for(i=0;i<n;i++) { for(j=0;j<nrhs;j++) { printf("%lf",b[i][j]); } printf("\ "); } } |
它不再正确编译(实际上我在macOS和ubuntu下都尝试过,存在相同的链接问题),并给出了链接错误消息(找不到符号LAPACKE_dgels):
1 2 3 4 5 6 7 | > Rcpp::sourceCpp("~/Desktop/demo3.cpp", showOutput = TRUE) /usr/lib/R/bin/R CMD SHLIB -o 'sourceCpp_6.so' 'demo3.cpp' g++ -I/usr/share/R/include -DNDEBUG -I"/home/yipan/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include" -I"/home/yipan/R/x86_64-pc-linux-gnu-library/3.4/lapacker/include" -I"/home/yipan/Desktop" -fpic -g -O2 -fdebug-prefix-map=/build/r-base-AitvI6/r-base-3.4.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c demo3.cpp -o demo3.o g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o sourceCpp_6.so demo3.o -L/usr/lib/R/lib -lR Error in dyn.load("/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so") : unable to load shared object '/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so': /tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so: undefined symbol: LAPACKE_dgels |
我还检查了/R/x86_64-pc-linux-gnu-library/3.4/lapacker/libs下的lapacker.so,发现:
1 | 000000000000c6b0 g DF .text 00000000000001bf Base LAPACKE_dgels |
我错过了一些东西来使demo3.cpp正确编译吗?非常感谢您的耐心和时间!
您在这里面临着一个难题。您尝试解析的
我确定CRAN上有使用方法4的示例,但现在还没有想到。但是,作为"代码kata",我已经转换了我最近的测试包以使用此结构c.f。 https://github.com/rstub/levmaR/tree/static。
(原始不完整答案。)
在
1 | PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) |
通过Rcpp属性编译cpp文件时,需要模拟设置。最好的方法是使用Rcpp插件c.f。 RcppArmadillo的解决方案(调整未经测试!):
1 2 3 4 5 6 7 8 9 10 11 | inlineCxxPlugin <- function(...) { plugin <- Rcpp::Rcpp.plugin.maker( include.before ="#include <lapacke.h>", libs ="$(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)", package ="lapacker" ) settings <- plugin() settings$env$PKG_CPPFLAGS <-"-I../inst/include" settings } |
顺便说一句,当RcppArmadillo已经这样??做时,为什么要直接与LAPACK交互?