Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ENH: linking LAPACK from C/C++ #20002

@ev-br

Description

@ev-br

Is your feature request related to a problem? Please describe.

cython_{blas,lapack} does a great job to make using LAPACK from Cython easy: just

from scipy.linalg.cython_lapack cimport dgeev

and you're up and running.

Using it from C or C++ should be as easy, but it currently isn't.

The ugly part is dealing with Fortran name mangling, which cython_lapack hides. It actually does the job internally:

$ ll build/scipy/linalg/_lapack_subroutine*
-rw-rw-r-- 1 br br 246836 янв 25 21:59 build/scipy/linalg/_lapack_subroutines.h
-rw-rw-r-- 1 br br  34384 янв 25 21:59 build/scipy/linalg/_lapack_subroutine_wrappers.f

Here _lapack_subroutines.h exports all the correctly named pointers:

$ less build/scipy/linalg/_lapack_subroutines.h
/* This file was generated by _generate_pyx.py. */
/* Do not edit this file directly. */

#ifndef SCIPY_LINALG_LAPACK_FORTRAN_WRAPPERS_H
#define SCIPY_LINALG_LAPACK_FORTRAN_WRAPPERS_H
#include "fortran_defs.h"
#include "numpy/arrayobject.h"

<snip>

#ifdef __cplusplus
extern "C" {
#endif

void F_FUNC(chla_transtypewrp, CHLA_TRANSTYPEWRP)(char *ret, int *trans);
void F_FUNC(cladivwrp, CLADIVWRP)(npy_complex64 *ret, npy_complex64 *x, npy_complex64 *y);
void F_FUNC(clangbwrp, CLANGBWRP)(float *ret, char *norm, int *n, int *kl, int *ku, npy_complex64 *ab, int *ldab, float *work);

...

so that #including _lapack_signatures looks like the solution for user code, and it even almost works.
Using e.g.

$ git diff
diff --git a/scipy/interpolate/meson.build b/scipy/interpolate/meson.build
index b9b3ed852b..eaa5e68c33 100644
--- a/scipy/interpolate/meson.build
+++ b/scipy/interpolate/meson.build
@@ -124,7 +124,7 @@ _bspl = py3.extension_module('_bspl',
   cython_gen.process('_bspl.pyx'),
   c_args: cython_c_args,
   include_directories: 'src/',
-  dependencies: np_dep,
+  dependencies: [lapack, np_dep],
   link_args: version_link_args,
   install: true,
   subdir: 'scipy/interpolate'
diff --git a/scipy/interpolate/src/__fitpack.h b/scipy/interpolate/src/__fitpack.h
index 97ac44a950..e70b081140 100644
--- a/scipy/interpolate/src/__fitpack.h
+++ b/scipy/interpolate/src/__fitpack.h
@@ -1,3 +1,22 @@
+
+#include "../linalg/_lapack_subroutines.h"
+

fails to build with

$ python dev.py build
<snip>
Found ninja-1.11.1 at /home/br/mambaforge/envs/scipy-dev/bin/ninja
Cleaning... 0 files.
[32/43] Compiling C object scipy/interpolate/_fitpack.cpython-310-x86_64-linux-gnu.so.p/src__fitpackmodule.c.o
FAILED: scipy/interpolate/_fitpack.cpython-310-x86_64-linux-gnu.so.p/src__fitpackmodule.c.o 
/home/br/mambaforge/envs/scipy-dev/bin/x86_64-conda-linux-gnu-cc -Iscipy/interpolate/_fitpack.cpython-310-x86_64-linux-gnu.so.p -Iscipy/interpolate -I../scipy/interpolate -I../scipy/interpolate/src -I../../../../mambaforge/envs/scipy-dev/lib/python3.10/site-packages/numpy/core/include -I/home/br/mambaforge/envs/scipy-dev/include/python3.10 -fvisibility=hidden -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c99 -O2 -g -Wno-unused-but-set-variable -Wno-unused-function -Wno-conversion -Wno-misleading-indentation -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/br/mambaforge/envs/scipy-dev/include -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -isystem /home/br/mambaforge/envs/scipy-dev/include -fPIC -DNPY_NO_DEPRECATED_API=NPY_1_9_API_VERSION -MD -MQ scipy/interpolate/_fitpack.cpython-310-x86_64-linux-gnu.so.p/src__fitpackmodule.c.o -MF scipy/interpolate/_fitpack.cpython-310-x86_64-linux-gnu.so.p/src__fitpackmodule.c.o.d -o scipy/interpolate/_fitpack.cpython-310-x86_64-linux-gnu.so.p/src__fitpackmodule.c.o -c ../scipy/interpolate/src/_fitpackmodule.c
In file included from ../scipy/interpolate/src/__fitpack.h:2,
                 from ../scipy/interpolate/src/_fitpackmodule.c:7:
scipy/interpolate/../linalg/_lapack_subroutines.h:6:10: fatal error: fortran_defs.h: No such file or directory
    6 | #include "fortran_defs.h"
      |          ^~~~~~~~~~~~~~~~
compilation terminated.
[33/43] Compiling C object scipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p/meson-generated__bspl.c.o
FAILED: scipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p/meson-generated__bspl.c.o 
/home/br/mambaforge/envs/scipy-dev/bin/x86_64-conda-linux-gnu-cc -Iscipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p -Iscipy/interpolate -I../scipy/interpolate -I../scipy/interpolate/src -I../../../../mambaforge/envs/scipy-dev/lib/python3.10/site-packages/numpy/core/include -I/home/br/mambaforge/envs/scipy-dev/include -I/home/br/mambaforge/envs/scipy-dev/include/python3.10 -fvisibility=hidden -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c99 -O2 -g -Wno-unused-but-set-variable -Wno-unused-function -Wno-conversion -Wno-misleading-indentation -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/br/mambaforge/envs/scipy-dev/include -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -isystem /home/br/mambaforge/envs/scipy-dev/include -fPIC -DNPY_NO_DEPRECATED_API=NPY_1_9_API_VERSION -DCYTHON_CCOMPLEX=0 -MD -MQ scipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p/meson-generated__bspl.c.o -MF scipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p/meson-generated__bspl.c.o.d -o scipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p/meson-generated__bspl.c.o -c scipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p/_bspl.c
In file included from ../scipy/interpolate/src/__fitpack.h:2,
                 from scipy/interpolate/_bspl.cpython-310-x86_64-linux-gnu.so.p/_bspl.c:1198:
scipy/interpolate/../linalg/_lapack_subroutines.h:6:10: fatal error: fortran_defs.h: No such file or directory
    6 | #include "fortran_defs.h"
      |          ^~~~~~~~~~~~~~~~

Describe the solution you'd like.

Have a canonical, single header file to include.

Describe alternatives you've considered.

Of course replicating the name mangling manually at include sites works:

diff --git a/scipy/interpolate/src/__fitpack.h b/scipy/interpolate/src/__fitpack.h
index 97ac44a950..e70b081140 100644
--- a/scipy/interpolate/src/__fitpack.h
+++ b/scipy/interpolate/src/__fitpack.h
@@ -1,3 +1,22 @@
+#include "../linalg/fortran_defs.h"
+
+#define DLARTG F_FUNC(dlartg, DLARTG)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void DLARTG(double *f, double *g, double *cs, double *sn, double *r);
+#ifdef __cplusplus
+}
+#endif

This is what we had here and there before cython_lapack.pxd, and I'd much prefer to not have these beauties sprinkled across the codebase :-).

I don't know if forward slashes in the include path are a problem on Windows. If they are, no biggie, can copy-paste the F_FUNC macro. But the point is it's ugly, it's brittle, it's error-prone, and it's reinventing a small wheel at each include site.

Additional context (e.g. screenshots, GIFs)

I'm mostly interested in internal usage in scipy. Whether we want to make this a part of the public SciPy contract (as cython_lapack is) is a separate question.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Build issuesIssues with building from source, including different choices of architecture, compilers and OSC/C++Items related to the internal C/C++ code baseenhancementA new feature or improvementmaintenanceItems related to regular maintenance tasks

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions