This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: Bug with ISO_C_BINDING on Mac OS?
- From: Tobias Burnus <burnus at net-b dot de>
- To: Janus Weil <janus at gcc dot gnu dot org>
- Cc: gfortran <fortran at gcc dot gnu dot org>
- Date: Sat, 01 Jun 2013 13:40:33 +0200
- Subject: Re: Bug with ISO_C_BINDING on Mac OS?
- References: <CAKwh3qhf9MsyRHR6Zcs+OZrY_kei0YGfSAuPz2RW9wziR2B=sA at mail dot gmail dot com>
Janus Weil wrote:
attached are two small test cases (Fortran & C), which try to open a
bz2 file for reading (they require a, possibly empty, file 'test.bz2'
in the same dir). The Fortran version uses ISO_C_BINDING interfaces
for the calls to 'fopen' and 'BZ2_bzReadOpen', and both work as
expected on Linux (x86_64):
Yes, there is a bug with ISO_C_BINDING - but the bug is in your code ;-)
At least the problem below is likely to cause problems on x86-64. I
don't know why you only see the problem on MacOS, it should also exist
on 64bit Linux.
You declare:
interface
function fOpen (path,mode) bind (c,NAME='fopen')
use, intrinsic :: ISO_C_BINDING
character(c_char) path(*),mode(*)
integer(c_int) :: fOpen
end function
end interface
However, POSIX defines that fopen returns a "FILE *". On most 32 bit
systems, it should work. However, on a 64bit system, it wont (or only by
chance). Either you should use a proper pointer like TYPE(c_ptr). Or, if
you want to use an integer, use: INTEGER(c_intptr_t).
interface
function bzReadOpen (bzerror,f,verbosity,small,unused,nUnused) bind (c,NAME='BZ2_bzReadOpen')
use, intrinsic :: ISO_C_BINDING
integer(c_int),value :: f,verbosity,small,nUnused
integer(c_int) :: bzReadOpen,bzerror
type(c_ptr) :: unused
end function
end interface
This one looks bogus as well. bzerror and f are both pointers (int * and
FILE *).
For bzerror: I think you really should use "INTEGER(c_int)" (w/o VALUE)
- that way you get a proper error return. If you use VALUE, you will
pass some random value which is in the actual argument, which will cause
problems.
And for FILE *f: Here, you have to ensure that you pass all 64bits of
the result value of "fopen". Again, I would use a "TYPE(C_PTR),VALUE"
which reflects the black box best. But using an
INTEGER(c_intptr_t),VALUE should also work. (Cf. above for "fopen".)
I can imagine two reasons that it works under Linux:
a) You get an error under MacOS but not under Linux, i.e. bzReadOpen
tries to write to "bzerror".
b) FILE * returns by chance a pointer address which fits into 32bit
under Linux but not under MacOS.
But there are surely more problems. In particular: bzReadOpen reads much
more argument values from the stack than you put there.
Frankly, I am still surprised that it (seems to) work on a 64bit Linux.
Tobias