Studying some of the Lapack wrappers over at LinearAlgebra.jl/src/lapack.jl at master · JuliaLang/LinearAlgebra.jl · GitHub, I am confused by the ccall
structure. Most relevant lapack methods have info
as their final argument according to the lapack documentation. However, the ccall
often adds a number of additional arguments of fixed value 1
and of type Clong
to the list of arguments, where the number of such arguments ranges is sometimes zero, sometimes one, sometimes two, up to sometimes four.
Why is this necessary and how can I know how many of these extra arguments are needed if I want to wrap other Lapack methods?
They are known as hidden arguments. Since the LAPACK and BLAS functions are Fortran functions that take some character arguments, the Fortran convention is to pass the length of the character arrays in the arguments as arguments at the end of the function.
Take the DGEBAK
function for instance. It has two arguments JOB
and SIDE
that are single-length character arrays (so a single character). Therefore, we include two arguments that are just 1
after the info argument to say that the JOB
and SIDE
arguments are only of length 1.
4 Likes
To complement Ian’s answer, you can read the Gfortran documentation about arguments passing conventions
For arguments of CHARACTER
type, the character length is passed as a hidden argument at the end of the argument list, except when the corresponding dummy argument is declared as TYPE(*)
. For deferred-length strings, the value is passed by reference, otherwise by value. The character length has the C type size_t
(or INTEGER(kind=C_SIZE_T)
in Fortran). Note that this is different to older versions of the GNU Fortran compiler, where the type of the hidden character length argument was a C int
. In order to retain compatibility with older versions, one can e.g. for the following Fortran procedure
subroutine fstrlen (s, a)
character(len=*) :: s
integer :: a
print*, len(s)
end subroutine fstrlen
define the corresponding C prototype as follows:
#if __GNUC__ > 7
typedef size_t fortran_charlen_t;
#else
typedef int fortran_charlen_t;
#endif
void fstrlen_ (char*, int*, fortran_charlen_t);
Note that this practice is assuming the code we’re calling was compiled with Gfortran (which is the case for the build of openblas shipped with julia) or another compiler with the same calling convention (which should be the case for most common fortran compilers around, in case you wanted to call a different blas/lapack library via libblastrampoline)
1 Like