- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

I read that Fortran assumed-*shape* arrays are not interoperable with C, but what about assumed-*size* arrays?

The BLAS library defines a subroutine CGEMM(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC), where:

COMPLEX A(LDA, *), B(LDB, *), C(LDC, *)

Is this subroutine callable by C? If so, are there any hidden arguments associated with the assumed-size arrays?

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

No hidden arguments - and there aren't in Fortran either with assumed-size arrays.

Interestingly, you can describe an assumed-size array in a C descriptor, but it's unclear to me how you would get Fortran to generate such a thing. I guess the idea is that a C routine could create it and the -1 last extent could be detected in your Fortran code. I have to give this some more thought...

Link Copied

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

No hidden arguments - and there aren't in Fortran either with assumed-size arrays.

Interestingly, you can describe an assumed-size array in a C descriptor, but it's unclear to me how you would get Fortran to generate such a thing. I guess the idea is that a C routine could create it and the -1 last extent could be detected in your Fortran code. I have to give this some more thought...

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

I understand they're interoperable, and the column-vs-row order implications. My question pertains more to how the dimension of the final rank would get across the interface. How does it happen with Fortran-calling-Fortran? If there isn't a hidden argument, is there a descriptor that's used (and publicly-defined) that I could utilize? Or is it just passed a reference to the first element? If so, how does the compiler know the memory stride of the second-to-last dimension?

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

@ereisch ,

Re: "My question pertains more to how the dimension of the final rank would get across the interface. How does it happen with Fortran-calling-Fortran?" - forever it's worth, I'll contend there is **NOT** a built-in mechanism.

What one finds is the same drawbacks since per-Fortran 90 days with assumed-size arrays i.e., the period prior to "explicit interfaces" persist in such scenarios. That is, the caller and callee need a "handshake" of some sort to ensure the dummy array argument(s) is(are) consumed in a manner the upper array bound(s) is(are) not exceeded. It's usually achieved via an explicit argument in the subprogram declaration rather than a hidden one that a compiler might provide.

Thus of course the proper way forward is refactored code or new code that makes use of assumed-shape arrays, etc. In this context, your statement, "I read that Fortran assumed-*shape* arrays are not interoperable with C" refers to Fortran 2003 and 2008. That is not accurate with current standard Fortran 2018.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

I retract my question about the compiler determining the stride size of the last dimension; I got wrapped around the axle between C and Fortran and forgot that Fortran is column-major, so the last dimension would only need to be known at compile time to enforce bounds checking; otherwise it wouldn't care.

I think I got the info I needed though; everything goes across as REFERENCE.

Thanks

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Assumed-size arrays depend on the called routine knowing, somehow, the array extent. The standard says the extent is from the first element in the passed argument to the last, but no information is transmitted to help with that. (There are some compilers that can optionally pass such info for diagnostic purposes.)

When you need to pass the size, prior to Fortran 90's assumed-shape arrays, one could use an "adjustable array", where the bounds are either explicitly passed in as separate arguments or come from COMMON. (As of Fortran 90 they could also come from a module or an uplevel scope.) Modern Fortran has assumed-shape arrays ,( : ) bounds, to pass all the necessary shape information.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

I finally figured this out... An assumed-size array can be passed to a procedure where the corresponding dummy argument is assumed-rank (a new F2018 concept). A dummy argument in an interoperable procedure can be assumed-rank. So if you pass an assumed-size array to such a dummy argument, a C descriptor is created. Here is an example:

```
module testmod
implicit none
contains
subroutine sub2 (array) bind(C)
integer, dimension(..), intent(in) :: array
select rank (array)
rank(*)
print *, "Assumed size!"
rank default
print *, "Not assumed size"
end select
end subroutine sub2
end module testmod
program test
use testmod
implicit none
integer :: a(10)
call sub1(a)
contains
subroutine sub1(a)
integer, dimension(*) :: a
call sub2(a)
end subroutine sub1
end program test
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

`.. It's usually achieved via an explicit argument in the subprogram declaration rather than a hidden one that a compiler might provide. ..`

This post is mostly for other readers who may prefer to see an actual example of how things work in terms of interoperability of modern Fortran with C.

As I mentioned earlier, when it comes to assumed-size arrays, their use in Fortran has also been "usually achieved via an explicit argument in the subprogram declaration"

One can see this with subprogram CGEMM from BLAS (LAPACK) library where a dummy argument 'A" is declared as 'COMPLEX, dimension(LDA,*) A' but note integer dummies K and M too are part of the argument list and the LAPACK documentation states:

```
A is COMPLEX array, dimension ( LDA, ka ), where ka is
k when TRANSA = 'N' or 'n', and is m otherwise.
Before entry with TRANSA = 'N' or 'n', the leading m by k
part of the array A must contain the matrix A, otherwise
the leading k by m part of the array A must contain the
matrix A.
```

Thus the needed info in terms of the upper bound of A is present interspersed among the argument list.

Now, note the Fortran standard mentions in NOTE 3 in Section 18.3.5 Interoperability of array variables,

```
For example, a Fortran array declared as
INTEGER(C_INT) :: A(18, 3:7, *)
is interoperable with a C array declared as
int b[][5][18];
```

With this in mind, a Fortran subprogram with an assumed-size array can be made to interoperate with C and for safety, an explicit argument to handle the array bounds is advised - similar to what one can see with CGEMM above. So say the Fortran code is written as follows with a subroutine Fsub.

```
module m
use, intrinsic :: iso_c_binding, only : c_int, c_size_t
enum, bind(C)
enumerator :: N = 3
end enum
contains
subroutine Fsub( x, m ) bind(C, name="Fsub")
integer(c_int), intent(inout) :: x(N,*)
integer(c_size_t), intent(in), value :: m
integer :: i
do i = 1, m
x(1, i) = 1
x(2, i) = 2
x(3, i) = 3
end do
return
end subroutine
end module
```

Note Fsub may be a wrapper to some legacy code in some library.

Now say the C caller is like so:

```
#include <stdio.h>
enum N { N = 3 };
// Fortran function prototype
void Fsub( int[][N], size_t );
int main(void)
{
enum M { M = 2 };
int x[M][N];
for (int i; i<2;i++) {
for (int j; j<3; j++ ) x[i][j] = 0;
}
Fsub( x, (size_t)M );
printf("Print from C main: following Fortran subroutine invocation, x = \n");
for (int i = 0; i<M; i++) {
for (int j = 0; j<N; j++ ) printf("%d ", x[i][j]);
}
printf("\n");
return 0;
}
```

Using Intel Fortran, the program works like so:

```
C:\Temp>ifort /c /standard-semantics /warn:all /stand:f18 f.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000
Copyright (C) 1985-2020 Intel Corporation. All rights reserved.
C:\Temp>cl /c /EHsc /W3 c.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28806 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
c.c
C:\Temp>link c.obj f.obj /subsystem:console /out:p.exe
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation. All rights reserved.
C:\Temp>p.exe
Print from C main: following Fortran subroutine invocation, x =
1 2 3 1 2 3
C:\Temp>
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

A typo in the C code in the prior thread: it should be

```
for (int i=0; i<2;i++) {
for (int j=0; j<3; j++ ) x[i][j] = 0;
}
```

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page