![](/img/trans.png)
[英]MinGW: Linking with LAPACK and BLAS causes C++ exceptions to become unhandled
[英]Linking C++ with BLAS and LAPACK
要从 C++ 调用 Fortran 例程,我一直在使用: extern "C" voidroutinename_(...) 并附加下划线,使其与 Fortran 子例程名称“ROUTINENAME”兼容。
当我将 c++ 与 BLAS 或 LAPACK 链接时,它只能在没有下划线的情况下工作。 将 c++ 与这些用 Fortran 编写的库链接起来有什么区别,这使得下划线变得不必要?
我可能是错的,因为要介绍的信息很少,但是......
从这里开始:第一个 F77 编译器在 ABI 中的函数名称后附加了一个_
。 此行为与 C 不同,C 仅采用函数名称并将其用作 ABI 中的名称。
一些编译器F77表现不同,代替上部壳体整个子程序的名称,以便foo()
成为FOO()
在由C. UNIX Fortran编译器看出模仿Ç行为,只是拷贝pasta'd名称,以便foo()
是foo()
也在 ABI 中。
但是,如果您查看此处的参考实现的 BLAS 绑定到 C,您会发现它们在处理 F77 时正在处理尾随下划线。 我敢打赌,在过去,下划线是 F77 ABI 的一个普遍特征,而不是没有它们。
后来,Fortran 2003 引入了与 C 的互操作性(请参阅此处)。 当使用某些 Fortran 构造时,这使得函数命名方案相同(请参阅此处)。
因此,我将疯狂猜测这与 Fortran 版本之间的 ABI 差异有关。 或者甚至只是跨编译器,因为不同的编译器在 Fortran 中似乎有不同的行为。
所以,再次,我不确定这是否与您的情况相匹配,因为您的问题没有太多可讨论的,但我无法将所有内容都放入评论中,所以这里是一个“答案” .
如果我错了,请告诉我,以便我更正 MAH 的帖子。
tl;dr:因为编译器版本
我将给出链接 BLAS 的一般答案,不仅是这个问题,还有这个问题的答案在下面的末尾。
首先,您需要确保使用(+lapack)安装了 BLAS
$ sudo apt-get install libblas-dev liblapack-dev
然后您可以在程序文件后使用 -lblas 进行链接。 或者您可以使用制作文件。
例如:g++ test.o dmatrix_denseCM.o mmio.o -o output -lblas
从我的角度来看,我更喜欢使用 OpenBlas,您可以在 makefile 中使用以下内容。
完成后,您应该拥有文件 libopenblas.a,即 openblas 库
这个目录OpenBLAS/libopenblas.a应该在同一个工作目录中。
.cc 文件中的示例代码:
extern "C"{
void dgemm_( const char &TRANSA, const char &TRANSB, const int &M, const int &N, const int & K, const double & ALPHA, const double *A, const int & LDA, const double *B, const int &LDB, const double &BETA, double *C, const int & LDC);
}
此外,当从 C 调用 LAPACK 或 BLAS 例程时,请注意,因为 Fortran 语言不区分大小写,所以例程名称可以是大写或小写,带有或不带有尾随下划线。 例如,以下名称是等效的:
LAPACK:dgetrf、DGETRF、dgetrf_ 和 DGETRF_
BLAS:dgemm、DGEMM、dgemm_ 和 DGEMM_ 英特尔® 数学核心函数库 11.3 更新 4 开发人员指南
您可以添加有关用于编译 BLAS 的 FORTRAN 编译器的更多信息,例如:
使用 -U 选项编译 Fortran 程序,该选项告诉编译器保留函数/子程序名称的现有大写/小写区别。
Fortran 编译器通常会在出现在入口点定义和调用中的子程序名称后附加下划线 (_)。 此约定不同于具有相同用户分配名称的 C 过程或外部变量。 这里
C++ 中的名称修改在 C 中产生了问题。因为 C 不支持重载,所以我们必须使用 extern "c"{}。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.