From: deadpickle on
Im trying to pass a real array to a C program. I declare the arguments
in the INTERFACE call using iso_c_binding:

INTERFACE
Subroutine
add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum) Bind(c,
Name='add_shp')
use iso_c_binding, only: c_int, c_double, c_char
implicit none
character (kind = c_char), dimension(*), Intent(IN) :: passer
integer (kind = c_int) , Intent(IN) :: eventnum, shpnum,tracknum
REAL (KIND = c_double), Intent(IN) :: shperror
REAL (KIND = c_double), dimension(:,:),Intent(IN) :: shparray
end subroutine add_shp
End interface

and pass the array to C. When I go to print in the C program I find
that nothing is in the array and it prints zeros. Am I passing the
array correctly? Oh and the array is allocatable.
From: Richard Maine on
deadpickle <deadpickle(a)gmail.com> wrote:

> Im trying to pass a real array to a C program. I declare the arguments
> in the INTERFACE call using iso_c_binding:
>
> INTERFACE
> Subroutine
> add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum) Bind(c,
> Name='add_shp')
> use iso_c_binding, only: c_int, c_double, c_char
> implicit none
> character (kind = c_char), dimension(*), Intent(IN) :: passer
> integer (kind = c_int) , Intent(IN) :: eventnum, shpnum,tracknum
> REAL (KIND = c_double), Intent(IN) :: shperror
> REAL (KIND = c_double), dimension(:,:),Intent(IN) :: shparray
> end subroutine add_shp
> End interface
>
> and pass the array to C. When I go to print in the C program I find
> that nothing is in the array and it prints zeros. Am I passing the
> array correctly? Oh and the array is allocatable.

The compiler shouldn't have even allowed this to compile. What compiler
accepted this? You can't have an assumed-shape dummy argument in a
bind(c) interface.

Since you don't show the corresponding C code, there is no way to know
exactly what would be correct. But it isn't this. The C code won't have
an assumed-shape array because there is no such thing in C. The whole
point of assumed shape is that the compiler passes the shape information
for you, "behind your back." A C compiler isn't going to know what to do
with that.

The actual argument being allocatable makes no difference as long as

1. It is allocated when you execute the call,

and

2. You don't have any ideas of changing the allocation (allocating or
deallocating) in the C code.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: deadpickle on
On Mar 8, 1:57 pm, nos...(a)see.signature (Richard Maine) wrote:
> deadpickle <deadpic...(a)gmail.com> wrote:
> > Im trying to pass a real array to a C program. I declare the arguments
> > in the INTERFACE call using iso_c_binding:
>
> > INTERFACE
> >               Subroutine
> > add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum) Bind(c,
> > Name='add_shp')
> >                       use iso_c_binding, only: c_int, c_double, c_char
> >                       implicit none
> >                       character (kind = c_char), dimension(*), Intent(IN) :: passer
> >                       integer (kind = c_int) , Intent(IN) :: eventnum, shpnum,tracknum
> >                       REAL (KIND = c_double), Intent(IN) :: shperror
> >                       REAL (KIND = c_double), dimension(:,:),Intent(IN) :: shparray
> >               end subroutine add_shp
> > End interface
>
> > and pass the array to C. When I go to print in the C program I find
> > that nothing is in the array and it prints zeros. Am I passing the
> > array correctly? Oh and the array is allocatable.
>
> The compiler shouldn't have even allowed this to compile. What compiler
> accepted this? You can't have an assumed-shape dummy argument in a
> bind(c) interface.
>
> Since you don't show the corresponding C code, there is no way to know
> exactly what would be correct. But it isn't this. The C code won't have
> an assumed-shape array because there is no such thing in C. The whole
> point of assumed shape is that the compiler passes the shape information
> for you, "behind your back." A C compiler isn't going to know what to do
> with that.
>
> The actual argument being allocatable makes no difference as long as
>
> 1. It is allocated when you execute the call,
>
> and
>
> 2. You don't have any ideas of changing the allocation (allocating or
> deallocating) in the C code.
>
> --
> Richard Maine                    | Good judgment comes from experience;
> email: last name at domain . net | experience comes from bad judgment.
> domain: summertriangle           |  -- Mark Twain

Sorry about that here is everything. The Fortran program is huge so
here are just the calls:
use iso_c_binding, Only: c_char, c_int, c_double

CHARActER(kind=c_char, len=200) :: passer
INTEGER(kind=c_int) :: eventnum,shpnum,tracknum
REAL(kind=c_double),ALLOCATABLE,DIMENSION(:,:) :: shparray
REAL(kind=c_double) :: shperror


FORTRAN BINDINGS/CALLS
INTERFACE
Subroutine add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum)
Bind(c, Name='add_shp')
use iso_c_binding, only: c_int, c_double, c_char
implicit none
character (kind = c_char), dimension(*), Intent(IN) :: passer
integer (kind = c_int) , Intent(IN) :: eventnum, shpnum,tracknum
REAL (KIND = c_double), Intent(IN) :: shperror
REAL (KIND = c_double), dimension(:,:),allocatable,Intent(IN) ::
shparray
end subroutine add_shp

End interface

CALL add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum)

C CALL
void add_shp(int *shpnum,int *eventnum,double shparray[2]
[*shpnum],double *shperror,char *passer,int *tracknum)
From: Richard Maine on
deadpickle <deadpickle(a)gmail.com> wrote:

> Sorry about that here is everything. The Fortran program is huge so
> here are just the calls:
> use iso_c_binding, Only: c_char, c_int, c_double
>
> CHARActER(kind=c_char, len=200) :: passer
> INTEGER(kind=c_int) :: eventnum,shpnum,tracknum
> REAL(kind=c_double),ALLOCATABLE,DIMENSION(:,:) :: shparray
> REAL(kind=c_double) :: shperror
>
>
> FORTRAN BINDINGS/CALLS
> INTERFACE
> Subroutine add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum)
> Bind(c, Name='add_shp')
> use iso_c_binding, only: c_int, c_double, c_char
> implicit none
> character (kind = c_char), dimension(*), Intent(IN) :: passer
> integer (kind = c_int) , Intent(IN) :: eventnum, shpnum,tracknum
> REAL (KIND = c_double), Intent(IN) :: shperror
> REAL (KIND = c_double), dimension(:,:),allocatable,Intent(IN) ::
> shparray
> end subroutine add_shp
>
> End interface
>
> CALL add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum)
>
> C CALL
> void add_shp(int *shpnum,int *eventnum,double shparray[2]
> [*shpnum],double *shperror,char *passer,int *tracknum)

I didn't know you could do that in C (the C-side declaration of
shparray). Can you? I guess I better defer to the more C fluent for
that. I could look it up, but I'd have to do so, and then study it for a
while.

In any case, note that the C code doesn't say anything about assumed
shape. It couldn't as there is no way to say such thing in C. That part
I do know. Your interface body has to match the actual C code. That's
what the interface body is for - to tell the compiler what the called
routine is like. If you lie to it by telling it that the called routine
has a different interface than the is so, things won't work well.

That C code looks like it is trying to declare the array as dimensioned
(2,shpnum) in Fortran terms. If that's the case, and if that really
works in C, then the corresponding way to declare the dimension in the
interface would be (2,shpnum) - not (:,:). See above comment about the
interface having to agree with the code.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: glen herrmannsfeldt on
Richard Maine <nospam(a)see.signature> wrote:
> deadpickle <deadpickle(a)gmail.com> wrote:

>> Sorry about that here is everything. The Fortran program is huge so
>> here are just the calls:
>> use iso_c_binding, Only: c_char, c_int, c_double
(snip)

>> INTERFACE
>> Subroutine add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum)
>> Bind(c, Name='add_shp')
>> use iso_c_binding, only: c_int, c_double, c_char
>> implicit none
>> character (kind = c_char), dimension(*), Intent(IN) :: passer
>> integer (kind = c_int) , Intent(IN) :: eventnum, shpnum,tracknum
>> REAL (KIND = c_double), Intent(IN) :: shperror
>> REAL (KIND = c_double), dimension(:,:),allocatable,Intent(IN) ::
>> shparray
>> end subroutine add_shp
>> End interface

>> CALL add_shp(shpnum,eventnum,shparray,shperror,passer,tracknum)

>> C CALL
>> void add_shp(int *shpnum,int *eventnum,double shparray[2]
>> [*shpnum],double *shperror,char *passer,int *tracknum)

> I didn't know you could do that in C (the C-side declaration of
> shparray). Can you? I guess I better defer to the more C fluent for
> that. I could look it up, but I'd have to do so, and then study it for a
> while.

It wouldn't surprise me if it was added in C99, but it isn't in C89.

C99 does allow dynamic sized automatic arrays, unlike C89,
so adding this makes some sense.

#include <stdio.h>
// test variable dimension dummy arrays
int main() {
int n=5;
float y[5][5];
fun(&n,y);
}
int fun(int *n,float x[*n][*n]) {
printf("%d %f\n",*n,x[3][3]);
}

Works with my version of gcc.

For C89, all array dimensions have to be compile time constants
(constant expressions), except the leftmost dimension on a dummy array.

> In any case, note that the C code doesn't say anything about assumed
> shape. It couldn't as there is no way to say such thing in C. That part
> I do know. Your interface body has to match the actual C code. That's
> what the interface body is for - to tell the compiler what the called
> routine is like. If you lie to it by telling it that the called routine
> has a different interface than the is so, things won't work well.

It would be nice if C programs could use a structure arranged to
match the descriptors used by Fortran. With that possibility,
it would be nice for compilers to allow passing assumed shape
to C, but I agree that there is no standard way to do it.

> That C code looks like it is trying to declare the array as dimensioned
> (2,shpnum) in Fortran terms. If that's the case, and if that really
> works in C, then the corresponding way to declare the dimension in the
> interface would be (2,shpnum) - not (:,:). See above comment about the
> interface having to agree with the code.

More usual C89 would be to declare it [][2], corresponding to
the Fortran assumed shape (2,*). That avoids the problem with
the variable dimension. Do remember the different subscript
order betweeen Fortran and C.

-- glen

 |  Next  |  Last
Pages: 1 2 3
Prev: The perpetual calendar
Next: Flowchart software