Prev: The perpetual calendar
Next: Flowchart software
From: deadpickle on 8 Mar 2010 14:33 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 8 Mar 2010 14:57 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 8 Mar 2010 15:38 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 8 Mar 2010 15:51 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 8 Mar 2010 16:32
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 |