문제
Clapack Atlas 라이브러리를 사용하는 C ++에서 프로그램을 작성하고 있습니다. 그러나 프로그램을 도서관에 성공적으로 연결할 수는 없습니다. 문제를 더 잘 보여주기 위해 작은 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 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)
도서관 :
$ 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의 역사적, 기능적 관계는 정확히 무엇입니까?
해결책
C ++ 프로그램을 C 라이브러리에 링크하려면 C 라이브러리의 모든 기능 등이 다음과 같은지 확인해야합니다. extern "C"
. C ++ 컴파일러는 C ++ 기호 이름을 관리하여 링커가 C 라이브러리의 이름과 기호와 일치하는 것이 불가능합니다. 블록을 사용하여 C 기호를 선언 할 수 있습니다.
extern "C" {
...
}
지시하기 위해 전처리 기호를 정의 할 수 있습니다. cblas.h
그리고 clapack.h
필요한 것을 포함합니다 extern "C"
모든 선언 앞에서.