I’ve tried the above code (with test_atnp.f90
and cfun.c
) on Ubuntu22 + gfortran-12 cfun.c test_atnp.f90
, then I get this error:
test_atnp.f90:68:34:
68 | ierr = cfun1_c(isize, ivals, C_NULL_PTR, C_NULL_PTR)
| 1
Error: Rank mismatch in argument ‘ivals2’ at (1) (rank-1 and scalar)
test_atnp.f90:68:46:
68 | ierr = cfun1_c(isize, ivals, C_NULL_PTR, C_NULL_PTR)
| 1
Error: Rank mismatch in argument ‘ivals3’ at (1) (rank-1 and scalar)
I haven’t tried Gfortran-13, but is the result different…?
By the way, I’ve tried using optional
also (as in the example by FortranFan), and it seems to work with gfortran-12. So I guess even for type(*)
, when the actual argument is absent, null pointers are sent to the optional dummy argument(s). (Below is a slightly modified code, where cfun1_opt_c()
is given optional
for ivalsN).
test_f.f90
Program test_atnp
USE ISO_FORTRAN_ENV
USE ISO_C_BINDING
Implicit NONE
Integer :: ivals(5), ierr2, ierr3, ierr1_opt, isize
Interface
Function cfun1_c(isize, ivals1, ivals2, ivals3) BIND(C, NAME="cfun")
IMPORT :: C_INT
implicit none
Integer(C_INT), VALUE :: isize
Type(*), Intent(IN) :: ivals1(*), ivals2(*), ivals3(*) !<-- no optional
Integer(C_INT) :: cfun1_c
End Function
Function cfun1_opt_c(isize, ivals1, ivals2, ivals3) BIND(C, NAME="cfun")
IMPORT :: C_INT
implicit none
Integer(C_INT), VALUE :: isize
Type(*), Intent(IN), optional :: ivals1(*), ivals2(*), ivals3(*) !<-- optional
Integer(C_INT) :: cfun1_opt_c
End Function
Function cfun2_c(isize, ivals1, ivals2, ivals3) BIND(C, NAME="cfun")
IMPORT :: C_INT, C_PTR
implicit none
Integer(C_INT), VALUE :: isize
Type(*), Intent(IN) :: ivals1(*)
Type(C_PTR), VALUE :: ivals2, ivals3
Integer(C_INT) :: cfun2_c
End Function
End Interface
ivals = [1, 2, 3, 4, 5]
isize = 5
Print *
Print *,'---- Calling ffun2 with type(c_ptr) interface ----'
Print *
Call ffun2(isize, ivals, ierr2)
Print *,''
Print *,' ffun2 ierr = ', ierr2
Print *
Print *,'---- Calling ffun3 with C_NULL_PTR in an array interface ----'
Print *
Call ffun3(isize, ivals, ierr3)
Print *
Print *,' ffun3 ierr = ', ierr3
Print *
Print *,'---- Calling ffun1_opt with an optional array interface ----'
Print *
Call ffun1_opt(isize, ivals, ierr1_opt)
Print *,''
Print *,' ffun1_opt ierr = ', ierr1_opt
Contains
Subroutine ffun2(isize, ivals, ierr)
Integer, Intent(IN) :: isize
Type(*), Intent(IN) :: ivals(*)
Integer, Intent(OUT) :: ierr
ierr = cfun2_c(isize, ivals, C_NULL_PTR, C_NULL_PTR)
End Subroutine
Subroutine ffun3(isize, ivals, ierr)
Integer, Intent(IN) :: isize
Type(*), Intent(IN) :: ivals(*)
Integer, Intent(OUT) :: ierr
Type(C_PTR) :: NULL_PTR(1)
NULL_PTR = C_NULL_PTR
!! NG: passing the address of NULL_PTR(:) array to cfun() in C.
ierr = cfun1_c(isize, ivals, NULL_PTR, NULL_PTR)
End Subroutine
Subroutine ffun1_opt(isize, ivals, ierr)
Integer, Intent(IN) :: isize
Type(*), Intent(IN) :: ivals(*)
Integer, Intent(OUT) :: ierr
!! (L-1) positional arguments only (where ivals2 and ivals3 are omitted)
ierr = cfun1_opt_c( isize, ivals )
!! (L-2) use keyword arguments (where ivals2 is omitted)
!! ierr = cfun1_opt_c( isize= isize, ivals1= ivals, ivals3= ivals )
End Subroutine
End Program
test_c.c
#include <stdio.h>
int cfun(
int isize,
const void *ival1,
const void *ival2,
const void *ival3 )
{
int i, ierr = 0;
if (ival1)
{
printf("ival1 array values\n\n");
for (i = 0; i < isize; i++) printf(" %d\n", ((int*) ival1)[i]);
ierr++;
}
if (ival2)
{
printf("ival2 array values\n\n");
for (i = 0; i < isize; i++) printf(" %d\n", ((int*) ival2)[i]);
ierr++;
}
if (ival3)
{
printf("ival3 array values\n\n");
for (i = 0; i < isize; i++) printf(" %d\n", ((int*) ival3)[i]);
ierr++;
}
printf("\n number of non-null pointers = %d\n", ierr);
return ierr;
}
Result (Ubuntu22):
$ gfortran-12 test_c.c test_f.f90
---- Calling ffun2 with type(c_ptr) interface ----
ival1 array values
1
2
3
4
5
number of non-null pointers = 1
ffun2 ierr = 1
---- Calling ffun3 with C_NULL_PTR in an array interface ----
ival1 array values
1
2
3
4
5
ival2 array values
0
0
-1149143776
32767
185058958
ival3 array values
0
0
-1149143776
32767
185058958
number of non-null pointers = 3
ffun3 ierr = 3
---- Calling ffun1_opt with an optional array interface ----
ival1 array values
1
2
3
4
5
number of non-null pointers = 1
ffun1_opt ierr = 1
If I use keyword arguments like (L-2), the result seems reasonable, so probably the code (+ gfortran-12) is working as expected for this usage?
---- Calling ffun1_opt with an optional array interface ----
ival1 array values
1
2
3
4
5
ival3 array values
1
2
3
4
5
number of non-null pointers = 2
ffun1_opt ierr = 2