2009-07-16 8 views
2

Я пишу программу на C++, которая использует библиотеку CLAPACK ATLAS. Тем не менее, я не могу заставить программу правильно связываться с библиотекой. Я написал небольшую программу C, чтобы лучше продемонстрировать проблему. Интересно, что эта небольшая демонстрационная программа очень удобна, если я скомпилирую ее с помощью GCC, но я получаю те же ошибки компоновщика, когда пытаюсь скомпилировать G ++. Я надеялся, что кто-то может помочь мне выяснить, что именно G ++ и GCC делают по-другому, чтобы получить ссылку на оригинальную программу (оригинальная программа - это программа на C++, и я не могу просто использовать GCC)C C++ Ошибка связи

Вот небольшая демонстрационная программа:

#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 и АТЛАС?

ответ

5

Если вы хотите связать программу C++ с библиотекой C, вы должны убедиться, что все функции и т. Д. В библиотеке C имеют префикс extern "C". Компилятор C++ управляет именами символов C++, что делает невозможным сопоставление компоновщика с символами с именами в библиотеке C. Вы можете использовать блок объявлять символы C:

extern "C" { 
    ... 
} 

Вы можете быть в состоянии определить символ препроцессора проинструктировать cblas.h и clapack.h включить необходимую extern "C" перед всеми декларациями.

+1

Спасибо, Мартин. Я завернул команды lapack и blas header #include в блоке extern «C» {}, и теперь он работает с G ++, потому что G ++ не знает, как манипулировать именами, когда дело касается объявления. – Litherum