| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| I try to use a C function returning a single character : char cdir(void){return '/';} Here is the test program (test.f90) MODULE mod INTERFACE FUNCTION cdir() BIND(C,name="cdir") RESULT(r) USE iso_c_binding CHARACTER(kind=C_CHAR) :: r END FUNCTION END INTERFACE END MODULE PROGRAM test USE mod WRITE(*,*) cdir() WRITE(*,*) ICHAR(cdir()) END PROGRAM Expected result : / 47 The results with 3 different compilers : g95 test.f90 cdir.o ../a.out 0 ifort test.f90 cdir.o ../a.out 63 gfortran test.f90 cdir.o => internal compiler error Versions used : g95 : gcc version 4.0.3 (g95 0.92!) Aug 21 2008 ifort :10.0 gfortran : 4.4.0 20080821 If I replace the function "cdir" by the procedure "getdir" , then all is OK : void getdir(char *c){*c='/';} MODULE mod INTERFACE SUBROUTINE getdir(c) BIND(C,name="getdir") USE iso_c_binding CHARACTER(kind=C_CHAR) :: c END SUBROUTINE END INTERFACE END MODULE PROGRAM test USE mod CHARACTER :: c CALL getdir(c) WRITE(*,*) c WRITE(*,*) ICHAR(c) END PROGRAM Results with the three compilers : / 47 |
|
#2
| |||
| |||
| On 22 aug, 16:21, fj <francois.j...@irsn.fr> wrote: > I try to use a C function returning a single character : > > char cdir(void){return '/';} > > Here is the test program (test.f90) > > MODULE mod > * INTERFACE > * * FUNCTION cdir() BIND(C,name="cdir") RESULT(r) > * * * USE iso_c_binding > * * * CHARACTER(kind=C_CHAR) :: r > * * END FUNCTION > * END INTERFACE > END MODULE > > PROGRAM test > * USE mod > * WRITE(*,*) cdir() > * WRITE(*,*) ICHAR(cdir()) > END PROGRAM > > Expected result : > */ > *47 > > The results with 3 different compilers : > > g95 test.f90 cdir.o > ./a.out > > 0 > > ifort test.f90 cdir.o > ./a.out > > 63 > > gfortran test.f90 cdir.o > => internal compiler error > > Versions used : > > g95 : gcc version 4.0.3 (g95 0.92!) Aug 21 2008 > ifort :10.0 > gfortran : 4.4.0 20080821 > > If I replace the function "cdir" by the procedure "getdir" , then all > is OK : > > void getdir(char *c){*c='/';} > > MODULE mod > * INTERFACE > * * SUBROUTINE getdir(c) BIND(C,name="getdir") > * * * USE iso_c_binding > * * * CHARACTER(kind=C_CHAR) :: c > * * END SUBROUTINE > * END INTERFACE > END MODULE > > PROGRAM test > * USE mod > * CHARACTER :: c > * CALL getdir(c) > * WRITE(*,*) c > * WRITE(*,*) ICHAR(c) > END PROGRAM > > Results with the three compilers : > / > 47 Hm, C is a bit funny when it comes to characters. They are almost but not entirely integers. Perhaps you ought to try: INTEGER :: r (And I can imagine the compilers focus on strings, rather individual characters ...) Regards, Arjen |
|
#3
| |||
| |||
| Arjen Markus <arjen.markus@wldelft.nl> wrote: > On 22 aug, 16:21, fj <francois.j...@irsn.fr> wrote: > > I try to use a C function returning a single character : > Hm, C is a bit funny when it comes to characters. They > are almost but not entirely integers. Perhaps you ought > to try: > INTEGER :: r No, that doesn't seem right. regardless of C's "funniness" with char type, the f2003 standard defines C char to interoperate with Fortran character(kind=c_char), as the OP does it. Perhaps one might be able to do a workaround along those lines, but that isn't the "right" solution for the f2003 C interop stuff. My suspicions would lie elsewhere. 1. Your function returns char instead of *char. I suppose that's probably ok and perhaps even the right thing to do, but it seems strange. I haven't worked through the implications, but something seems awry here in that I don't see how the same interface could correctly describe both a function returning char and another one returning *char. Heck, that's back to one of the eternal problems with writing and interfacing with C code - getting off by one in the level of pointer indirection. 2. Character is so much a special case, and functions returning character even more so, that it wouldn't shock me for compilers not to have gotten that right yet. But all 3 compilers getting it wrong would seem to greatly lower the odds of that. -- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain |
|
#4
| |||
| |||
| On 22 Aug., 19:47, nos...@see.signature (Richard Maine) wrote: > Arjen Markus <arjen.mar...@wldelft.nl> wrote: > > They > > are almost but not entirely integers. Perhaps you ought > > to try: > > INTEGER :: r I think that should work - with INTEGER(C_SIGNED_CHAR). However, before you can print the result, you need to transfer the INTEGER(C_SIGNED_CHAR) to character. Otherwise I believe the program is valid - and NAG f95 also works with it. > 1. Your function returns char instead of *char. I suppose that's > probably ok and perhaps even the right thing to do, but it seems > strange. Why? integer(c_int) also returns an int and not an int*. (Remember that only length-1 characters are allowed with bind(C).) > I haven't worked through the implications, but something seems > awry here in that I don't see how the same interface could correctly > describe both a function returning char and another one returning *char. That's simple: for char* you need a pointer, i.e. type(c_ptr). The extra indirection only comes into play for the arguments due to Fortran's call by reference. Tobias |
|
#5
| |||
| |||
| Arjen Markus wrote: (snip) > Hm, C is a bit funny when it comes to characters. They > are almost but not entirely integers. Perhaps you ought > to try: > INTEGER :: r > (And I can imagine the compilers focus on strings, rather > individual characters ...) C character constants are integers. (try sizeof('/')) char and short function arguments are normally converted to int before function calls. That may also tend to happen with function return values. A proper C interoperability implementation will know about the return convention, but it might take a while to get there. Yes, I wouldn't be surprised if a C function of type char returned an int. -- glen |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.