2009-07-16 7 views
2

J'écris un programme en C++ qui utilise la bibliothèque CLAPACK ATLAS. Cependant, je ne parviens pas à lier correctement le programme à la bibliothèque. J'ai écrit un petit programme C pour mieux démontrer le problème. Chose intéressante, ce petit programme de démonstration est très bien si je le compile avec GCC, mais j'ai les mêmes erreurs d'éditeur de liens quand j'essaie de compiler avec G ++. J'espérais que quelqu'un pourrait m'aider à comprendre exactement ce que G ++ et GCC font différemment, afin de lier le programme original (Le programme original est un programme C++ et je ne peux pas simplement "utiliser GCC")C C++ Erreur de liaison

Voici le petit programme de démonstration:

#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; 
} 

Et quand je tente de compiler ce avec GCC, il fonctionne très bien:

$ 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 

$ 

Et quand je tente de compiler cela avec G ++, il donne des erreurs d'éditeur de liens :

$ 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: Quelques informations sur mon système:
Système d'exploitation: 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)
Bibliothèques:

$ 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 

En outre, pour les points de bonus: Quelle est exactement la relation historique et fonctionnelle entre LAPACK et ATLAS?

Répondre

5

Si vous voulez lier un programme C++ à une bibliothèque C, vous devez vous assurer que toutes les fonctions de la bibliothèque C sont préfixées par extern "C". Le compilateur C++ altère les noms de symboles C++, ce qui empêche le lieur de faire correspondre les symboles avec les noms de la bibliothèque C. Vous pouvez utiliser un bloc pour déclarer vos symboles C:

extern "C" { 
    ... 
} 

Vous pouvez être en mesure de définir un symbole de préprocesseur pour instruire cblas.h et clapack.h d'inclure la extern "C" nécessaire devant toutes les déclarations.

+1

Merci, Martin. J'ai enveloppé la lapack et blas les en-têtes #include dans un bloc externe "C" {}, et maintenant cela fonctionne avec G ++, parce que G ++ sait ne pas altérer les noms quand ils rencontrent la déclaration. – Litherum