C C++ 链接错误
我正在用 C++ 编写一个程序,它使用 CLAPACK ATLAS 库。 但是,我无法让程序成功链接到库。 我编写了一个小型 C 程序来更好地演示该问题。 有趣的是,如果我用 GCC 编译这个小演示程序,它链接得很好,但当我尝试用 G++ 编译时,我会得到相同的链接器错误。 我希望有人能帮我弄清楚 G++ 和 GCC 的不同之处,以便链接原始程序(原始程序是 C++ 程序,我不能只是“使用 GCC”)
这是小演示程序:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <cblas.h>
#include <clapack.h>
// a is a column-major array of all the values in the matrix to invert
// The matrix's height and width are the same because it is a square matrix.
void invertMatrix(float *a, unsigned int height)
{
int info, ipiv[height];
info = clapack_sgetrf(CblasColMajor, height, height, a, height, ipiv);
info = clapack_sgetri(CblasColMajor, height, a, height, ipiv);
}
void displayMatrix(float *a, unsigned int height, unsigned int width)
{
int i, j;
for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
{
printf("%1.3f ", a[height*j + i]);
}
printf("\n");
}
printf("\n");
}
void multiplyMatrix(float *a, unsigned int aheight, unsigned int awidth, float *b, unsigned int bwidth, float *c)
{
cblas_sgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, aheight, bwidth, awidth, 1.0f, a, aheight, b, awidth, 0.0f, c, aheight);
}
int main(int argc, char *argv[])
{
int i;
float a[9], b[9], c[9];
srand(time(NULL));
for(i = 0; i < 9; i++)
{
a[i] = 1.0f*rand()/RAND_MAX;
b[i] = a[i];
}
displayMatrix(a, 3, 3);
invertMatrix(a, 3);
multiplyMatrix(a, 3, 3, b, 3, c);
displayMatrix(c, 3, 3);
return 0;
}
当我尝试用 GCC 编译它时,它工作得很好:
$ gcc -o linearalgebra linearalgebra.c -I /usr/include/atlas -L /usr/lib64/atlas/ -llapack -lblas
$ ./linearalgebra
0.723 0.755 0.753
0.179 0.912 0.349
0.642 0.265 0.530
1.000 -0.000 0.000
0.000 1.000 0.000
0.000 0.000 1.000
$
当我尝试用 G++ 编译它时,它给出了链接器错误:
$ g++ -o linearalgebra linearalgebra.c -I /usr/include/atlas -L /usr/lib64/atlas/ -llapack -lblas
/tmp/ccuhmDKE.o: In function `multiplyMatrix(float*, unsigned int, unsigned int, float*, unsigned int, float*)':
linearalgebra.c:(.text+0x7b): undefined reference to `cblas_sgemm(CBLAS_ORDER, CBLAS_TRANSPOSE, CBLAS_TRANSPOSE, int, int, int, float, float const*, int, float const*, int, float, float*, int)'
/tmp/ccuhmDKE.o: In function `invertMatrix(float*, unsigned int)':
linearalgebra.c:(.text+0x182): undefined reference to `clapack_sgetrf(CBLAS_ORDER, int, int, float*, int, int*)'
linearalgebra.c:(.text+0x1a0): undefined reference to `clapack_sgetri(CBLAS_ORDER, int, float*, int, int const*)'
collect2: ld returned 1 exit status
$
最后但并非最不重要的:有关我的系统的一些信息:
操作系统:Fedora 10(Linux 主机名 2.6.27.25-170.2.72.fc10.x86_64 #1 SMP Sun Jun 21 18:39:34 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux)
图书馆:
$ yum list | grep lapack
lapack.x86_64 3.1.1-4.fc10 installed
lapack-debuginfo.x86_64 3.1.1-4.fc10 installed
lapack-devel.x86_64 3.1.1-4.fc10 @fedora
$ yum list | grep blas
blas.x86_64 3.1.1-4.fc10 installed
blas-devel.x86_64 3.1.1-4.fc10 installed
$ yum list | grep atlas
atlas.x86_64 3.6.0-15.fc10 installed
atlas-debuginfo.x86_64 3.6.0-15.fc10 installed
atlas-devel.x86_64 3.6.0-15.fc10 @fedora
另外,为了加分:LAPACK 和 ATLAS 之间的历史和功能关系到底是什么?
I am writing a program in C++ which uses the CLAPACK ATLAS library. However, I cannot get the program to link successfully to the library. I have written a small C program to better demonstrate the problem. Interestingly enough, this small demonstration program links just fine if I compile it with GCC, but I get the same linker errors when I try to compile with G++. I was hoping someone could help me figure out exactly what G++ and GCC are doing differently, so as to get the original program to link (The original program is a C++ program and I can't just "use GCC")
Here is the small demonstration program:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <cblas.h>
#include <clapack.h>
// a is a column-major array of all the values in the matrix to invert
// The matrix's height and width are the same because it is a square matrix.
void invertMatrix(float *a, unsigned int height)
{
int info, ipiv[height];
info = clapack_sgetrf(CblasColMajor, height, height, a, height, ipiv);
info = clapack_sgetri(CblasColMajor, height, a, height, ipiv);
}
void displayMatrix(float *a, unsigned int height, unsigned int width)
{
int i, j;
for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
{
printf("%1.3f ", a[height*j + i]);
}
printf("\n");
}
printf("\n");
}
void multiplyMatrix(float *a, unsigned int aheight, unsigned int awidth, float *b, unsigned int bwidth, float *c)
{
cblas_sgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, aheight, bwidth, awidth, 1.0f, a, aheight, b, awidth, 0.0f, c, aheight);
}
int main(int argc, char *argv[])
{
int i;
float a[9], b[9], c[9];
srand(time(NULL));
for(i = 0; i < 9; i++)
{
a[i] = 1.0f*rand()/RAND_MAX;
b[i] = a[i];
}
displayMatrix(a, 3, 3);
invertMatrix(a, 3);
multiplyMatrix(a, 3, 3, b, 3, c);
displayMatrix(c, 3, 3);
return 0;
}
And when I try to compile this with GCC, it works just fine:
$ gcc -o linearalgebra linearalgebra.c -I /usr/include/atlas -L /usr/lib64/atlas/ -llapack -lblas
$ ./linearalgebra
0.723 0.755 0.753
0.179 0.912 0.349
0.642 0.265 0.530
1.000 -0.000 0.000
0.000 1.000 0.000
0.000 0.000 1.000
$
And when I try to compile this with G++, it gives linker errors:
$ g++ -o linearalgebra linearalgebra.c -I /usr/include/atlas -L /usr/lib64/atlas/ -llapack -lblas
/tmp/ccuhmDKE.o: In function `multiplyMatrix(float*, unsigned int, unsigned int, float*, unsigned int, float*)':
linearalgebra.c:(.text+0x7b): undefined reference to `cblas_sgemm(CBLAS_ORDER, CBLAS_TRANSPOSE, CBLAS_TRANSPOSE, int, int, int, float, float const*, int, float const*, int, float, float*, int)'
/tmp/ccuhmDKE.o: In function `invertMatrix(float*, unsigned int)':
linearalgebra.c:(.text+0x182): undefined reference to `clapack_sgetrf(CBLAS_ORDER, int, int, float*, int, int*)'
linearalgebra.c:(.text+0x1a0): undefined reference to `clapack_sgetri(CBLAS_ORDER, int, float*, int, int const*)'
collect2: ld returned 1 exit status
$
Last but not least: Some information about my system:
Operating System: Fedora 10 (Linux hostname 2.6.27.25-170.2.72.fc10.x86_64 #1 SMP Sun Jun 21 18:39:34 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux)
Libraries:
$ yum list | grep lapack
lapack.x86_64 3.1.1-4.fc10 installed
lapack-debuginfo.x86_64 3.1.1-4.fc10 installed
lapack-devel.x86_64 3.1.1-4.fc10 @fedora
$ yum list | grep blas
blas.x86_64 3.1.1-4.fc10 installed
blas-devel.x86_64 3.1.1-4.fc10 installed
$ yum list | grep atlas
atlas.x86_64 3.6.0-15.fc10 installed
atlas-debuginfo.x86_64 3.6.0-15.fc10 installed
atlas-devel.x86_64 3.6.0-15.fc10 @fedora
Also, for bonus points: What exactly is the historical and functional relationship between LAPACK and ATLAS?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果要将 C++ 程序链接到 C 库,则必须确保 C 库中的所有函数等都以
extern "C"
为前缀。 C++ 编译器会破坏 C++ 符号名称,这使得链接器无法将符号与 C 库中的名称进行匹配。 您可以使用块来声明您的 C 符号:您可以定义一个预处理器符号来指示
cblas.h
和clapack.h
包含必要的extern "C"
位于所有声明前面。If you want to link a C++ program to a C library you have to make sure that all functions etc. in the C library is prefixed with
extern "C"
. The C++ compiler mangles C++ symbol names which makes it impossible for the linker to match then symbols with the names in the C library. You can use a block to declare your C symbols:You may be able to define a preprocessor symbol to instruct
cblas.h
andclapack.h
to include the necessaryextern "C"
in front of all declarations.