2017-09-11 5 views
4

J'utilise Lapack dans mon code C++. Je suis assez confus comment correctement lier à la bibliothèque. Voici un petit exemple correspondant à mon code appelant une fonction de Lapack:Lien vers la bibliothèque Fortran (Lapack) à partir de C++

#include <iostream> 

namespace lapack { extern "C" { 
    void ilaver(int* major, int* minor, int* patch); } } 

int main() 
{ 
    int major = 0; 
    int minor = 0; 
    int patch = 0; 
    lapack::ilaver(&major, &minor, &patch); 
    std::cout << major << "." << minor << "." << patch << std::endl; 
    return 0; 
} 

Si je tente de le compiler avec GCC 4.8.5 (Linux openSUSE), je reçois l'erreur suivante:

> g++ ilaver.cpp -o ilaver -L /softs/lapack/3.7.1/64/gcc/4.8.5/lib64 -l lapack 
/tmp/ccHvDCAh.o: In function `main': 
ilaver.cpp:(.text+0x33): undefined reference to `ilaver' 
collect2: error: ld returned 1 exit status 

J'ai compris que c'était un problème de mangling. Si je change mon code en ajoutant un trait de soulignement à la fin du nom de la fonction, il compile correctement avec GCC:

#include <iostream> 

namespace lapack { extern "C" { 
    void ilaver_(int* major, int* minor, int* patch); } } 

int main() 
{ 
    int major = 0; 
    int minor = 0; 
    int patch = 0; 
    lapack::ilaver_(&major, &minor, &patch); 
    std::cout << major << "." << minor << "." << patch << std::endl; 
    return 0; 
} 

Mais il ne compile pas avec les compilateurs d'Intel sous Windows. Là, le mangling est différent, je dois le changer en lapack::ILAVER, puis il compile.

Mon code doit être compilé sous plusieurs configurations (Linux/Mac/Windows) avec plusieurs compilateurs (GCC, Intel, MSVC). Comment puis-je être plus générique et être sûr qu'il sera compilé sous un grand panel de compilateurs?

+2

Utilisez simplement lapacke. Ils ont déjà fait toute la supercherie dégueulasse nécessaire pour que cela fonctionne et c'est l'interface C officielle. –

Répondre

2

Comme vous l'avez déjà découvert, les hacks comme l'ajout du trait de soulignement sont spécifiques à la plate-forme par leur nature. Soutenir un grand nombre de plates-formes et de compilateurs de cette manière nécessite un travail fastidieux et fastidieux.

La façon la plus simple d'obtenir la portabilité est d'utiliser LAPACKE, l'interface C officielle de LAPACK. Cela a également l'avantage de vous éviter d'avoir à re-déclarer toutes les fonctions dont vous avez besoin.

Voici un exemple simple:

#include <iostream> 
#include <lapacke.h>  

int main() 
{ 
    // By using lapack_int, we also support LAPACK-ILP64 
    lapack_int major = 0; 
    lapack_int minor = 0; 
    lapack_int patch = 0; 
    LAPACKE_ilaver(&major, &minor, &patch); 
    std::cout << major << "." << minor << "." << patch << std::endl; 
    return 0; 
} 

Plus d'informations peuvent être trouvées dans le official documentation.

Notez que LAPACKE ne gère que LAPACK, si vous avez également besoin de routines BLAS, vous pouvez obtenir ceux de CBLAS.

+0

Cela pourrait être une solution, mais lapacke n'est pas installé par défaut sur les différentes configurations que nous utilisons. Il induit un surcoût pour mettre à jour toute l'installation de lapack sur toutes les configurations. – Caduchon

+2

@Caduchon J'ai entendu cet argument auparavant, mais je peux vous dire que l'installation et la mise à jour de lapacke sont bien plus rapides et faciles que l'écriture et la maintenance de lapacke maison. –

+0

Est-ce que lapacke contient également des fonctions BLAS (blas a été donné avec lapack quand je l'ai compilé)? Je ne peux pas trouver 'dgemm' (je l'utilise). – Caduchon