5

I have a Fortran subroutine taking an assumed size array:

subroutine sub(arr)
  implicit none
  double precision arr(*)
end subroutine

I made a native call from Java using JNA, the Fortran subroutine is compiled as a shared library mylib.so:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class Wrapper {
    public interface MyLib extends Library {
        public void sub_(double[] arr);
    }

    public static void main(String[] args) {
        System.setProperty("jna.library.path", ".");
        MyLib lib = (MyLib) Native.loadLibrary("mylib.so", MyLib.class);
        double[] myarr = new double[10];
        lib.sub_(myarr);
    }
}

Now, is there a way to get (in the Fortran subroutine) the size of the array I passed into this subroutine without passing the actual size (10 in this case) as an additional argument?

I tried (Fortran) print*, size(arr), but that gives a compiler error:

   print*,size(arr)
              1
Error: The upper bound in the last dimension must appear in the reference to the assumed size array ‘arr’ at (1)
francescalus
  • 30,576
  • 16
  • 61
  • 96
Raphael Roth
  • 26,751
  • 15
  • 88
  • 145

1 Answers1

7

You will need to pass the length as an additional parameter. Using an assumed-shape array will not work, here's why:

In the ABI employed by most Fortran compilers, arrays as parameters ("dummy arguments") can take one of two representations, depending on the interface used in the subroutine/function:

  • Those passed with known sizes or assumed sizes, like arr(n) or arr(*), usually receive just a pointer to the first element, with elements assumed to be contiguous.
  • Those passed with assumed shapes, like arr(:) receive an array descriptor structure. This is completely implementation dependent, but usually such a structure contains the pointer to the first element of the data plus information on the bounds of each dimension, the stride, etc.

That is the reason why you can directly pass a single row, or only the elements in even indices, of an array if the function receives it as an assumed shape array: the descriptor structure encodes the information that the data is not necessarily contiguous and so the Fortran compiler does not need to copy arr(5:2:) to a temporary location in memory.

The reason why you cannot use such facilities to communicate with Java is that the descriptor structure is completely non-standard, a part of the particular ABI of each compiler. Thus, even if you somehow managed to understand how to build it (and it would be non trivial) the next version of your compiler could bring a total change.

Javier Martín
  • 2,537
  • 10
  • 15
  • Actually, main parts of the descriptor are now standardized in a TS which is to become a part of Fortran 2015. There are even standard headers for using assumed shape arrays in Cm but I don't know if any compiler actually ships them yet. Unfortunately, gfortran's descriptor is still very different, unlike other compilers. – Vladimir F Героям слава Jun 08 '16 at 20:59
  • 1
    @VladimirF the problem with something getting standardized in F2015 is that most compilers don't even implement the full extent of F2008. You need to consider a significant delay, easily 10 years, if some feature is to be assumed "universally available" in a standard-compliant way. As an example, Intel Fortran 12.0 (2011?) did not implement the `ALLOCATE(x, SOURCE=y)` statement from Fortran 2003. – Javier Martín Jun 08 '16 at 22:56
  • It was standardized to just describe what compilers actually use. Intel actually already implements the now standard version for many years. Gfortran devs also know they need to change it for many years but they have some complications. – Vladimir F Героям слава Jun 08 '16 at 23:00
  • I must correct my previous comments. In a different place on this server Steve Lionel from Intel pointed out that the standard array descriptor only concerns procedures interoperable with C. Within Fortran the compilers can use and often actually use some other format of the descriptor. – Vladimir F Героям слава Nov 25 '17 at 21:46
  • 1
    1) Intel Fortran 17 supports ALL of the F2015 "Further Interoperability with C" features, including C descriptors for deferred-shape arrays. Javier would need to add BIND(C) to the Fortran procedure declaration and the Java code would need to construct an implementation-dependent C descriptor. (Some of the layout of the descriptor is compiler-specific - compilers provide a .h file with the layout.) 2) Vladimir is correct that C descriptors are not used for calls to Fortran routines that don't have BIND(C). It seems to me that passing the lengths is the easiest approach here. – Steve Lionel Nov 25 '17 at 22:17