4

I'm using Lapack in my C++ code. I'm quite confused how to properly link to the library. Here is a small example corresponding to my code calling a function from Lapack:

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

If I try to compile it with GCC 4.8.5 (Linux openSUSE), I get the following error:

> 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

I understood it's a name mangling problem. If I change my code adding an underscore at the end of the function name, it compiles properly with 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;
}

But it doesn't compile with Intel's compilers under Windows. There, the mangling is different, I have to change it to lapack::ILAVER, and then it compiles.

My code must be compiled under several configurations (Linux/Mac/Windows) with several compilers (GCC,Intel,MSVC). How can I be more generic and be sure it will compile under a large panel of compilers ?

Caduchon
  • 4,574
  • 4
  • 26
  • 67
  • 2
    Just use lapacke. They have already done all the disgusting macro trickery needed to get this to work and it's the official C interface. – Baum mit Augen Sep 11 '17 at 12:34

1 Answers1

2

As you have already discovered, hacks like adding the underscore are platform-specific by their nature. Supporting a big range of platforms and compilers that way "by hand" requires a large amount of unpleasant and tedious work.

The easiest way to get portability is to use LAPACKE, the official C interface to LAPACK. This also has the added benefit of saving you from having to re-declare all the functions you need.

Here's a simple example:

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

More information can be found in the official documentation.

Note that LAPACKE only handles LAPACK, if you also need BLAS routines, you can get those from CBLAS.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • It could be a solution, but lapacke is not installed by default on the different configurations we use. It induces an additional cost to update all the installation of lapack on all the configurations. – Caduchon Sep 11 '17 at 12:47
  • 2
    @Caduchon I've heard that argument before, but I can tell you that installing and updating lapacke is way faster and easier than writing and maintaining some home-brewed lapacke yourself. – Baum mit Augen Sep 11 '17 at 12:49
  • Does lapacke also contain BLAS functions (blas was given with lapack when I compiled it) ? I can't find `dgemm` (I use it). – Caduchon Sep 11 '17 at 12:53
  • 2
    @Caduchon The Blas routines are in [CBLAS](http://www.netlib.org/blas/#_cblas), lapacke just handles lapack. – Baum mit Augen Sep 11 '17 at 12:55