2 Stimmen

C C++ Verknüpfungsfehler

Ich schreibe ein Programm in C++, das die CLAPACK ATLAS-Bibliothek verwendet. Allerdings kann ich das Programm nicht erfolgreich mit der Bibliothek verknüpfen. Ich habe ein kleines C-Programm geschrieben, um das Problem besser zu demonstrieren. Interessanterweise verknüpft sich dieses kleine Demonstrationsprogramm problemlos, wenn ich es mit GCC kompiliere, aber wenn ich es mit G++ kompiliere, erhalte ich die gleichen Linker-Fehler. Ich hoffe, dass mir jemand helfen kann, genau herauszufinden, was G++ und GCC anders machen, um das ursprüngliche Programm zu verknüpfen (Das ursprüngliche Programm ist ein C++-Programm, und ich kann nicht einfach "GCC verwenden")

Hier ist das kleine Demonstrationsprogramm:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <cblas.h>
#include <clapack.h>

// a ist ein spaltenweise angeordnetes Array aller Werte in der zu invertierenden Matrix. Die Höhe und Breite der Matrix sind gleich, da es sich um eine quadratische Matrix handelt.
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;
}

Und wenn ich das mit GCC kompilieren, funktioniert es einwandfrei:

$ 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

$

Und wenn ich das mit G++ kompilieren, erhalte ich Linkerfehler:

$ 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
$

Zu guter Letzt: Einige Informationen über mein System:
Betriebssystem: 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)
Bibliotheken:

$ yum list | grep lapack
lapack.x86_64                        3.1.1-4.fc10                 installiert
lapack-debuginfo.x86_64              3.1.1-4.fc10                 installiert
lapack-devel.x86_64                  3.1.1-4.fc10                 @fedora
$ yum list | grep blas
blas.x86_64                          3.1.1-4.fc10                 installiert
blas-devel.x86_64                    3.1.1-4.fc10                 installiert
$ yum list | grep atlas
atlas.x86_64                         3.6.0-15.fc10                installiert
atlas-debuginfo.x86_64               3.6.0-15.fc10                installiert
atlas-devel.x86_64                   3.6.0-15.fc10                @fedora

Zu guter Letzt, für Bonuspunkte: Was genau ist die historische und funktionale Beziehung zwischen LAPACK und ATLAS?

5voto

Martin Liversage Punkte 100306

Wenn Sie ein C++-Programm mit einer C-Bibliothek verknüpfen möchten, müssen Sie sicherstellen, dass alle Funktionen usw. in der C-Bibliothek mit extern "C" vorausgehen. Der C++-Compiler verändert die Namen der C++-Symbole, was es dem Linker unmöglich macht, diese Symbole mit den Namen in der C-Bibliothek abzugleichen. Sie können einen Block verwenden, um Ihre C-Symbole zu deklarieren:

extern "C" {
  ...
}

Sie können möglicherweise ein Präprozessor-Symbol definieren, um cblas.h und clapack.h anzuweisen, das erforderliche extern "C" vor allen Deklarationen einzuschließen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X