# Endianness doesn't seem to be conserved in FORTRAN shared libraries?

**URL:** <https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174>\
**Category:** General Usage\
**Tags:** question, fortran\
**Created:** [November 15, 2020, 5:59am UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174 "2020-11-15T05:59:40Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![ctessum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ctessum/32/19444_2.png) [@ctessum](https://discourse.julialang.org/u/ctessum)\
**Post date:** [November 15, 2020, 5:59am UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/1 "2020-11-15T05:59:40Z")

</div>

Hello! I have a question regarding calling a FORTRAN shared library that needs to read a binary file that is big-endian.

This is the file in question: [https://github.com/wrf-model/WRF/blob/master/run/RRTMG\_LW\_DATA](https://github.com/wrf-model/WRF/blob/master/run/RRTMG_LW_DATA).

I can write some fortran to read the file:

```julia
content = """
real(kind=selected_real_kind(12)) :: fracrefao(16)

OPEN(10,FILE='RRTMG_LW_DATA', &
    FORM='UNFORMATTED',STATUS='OLD')

READ (10) fracrefao

WRITE (*, *) fracrefao
"""

```

and then put it in a program:

```julia
prog = "program p\n" * content * "\nend program p\n"

open("read_file.f90", "w") do f
    write(f, prog)
end

```

and compile and run it:

```julia
run(`gfortran -O2 -fconvert=big-endian read_file.f90 -o read_file.exe`)

run(`./read_file.exe`)

```

This all works fine, but only if I use `-fconvert=big-endian` to do big-endian IO. If I don’t use that flag, I get this error:

```julia
At line 5 of file read_file.f90 (unit = 10, file = 'RRTMG_LW_DATA')
Fortran runtime error: End of file

```

What I really want to do, however, is to call a fortran shared library from julia to do the reading:

```julia
mod = """module m
contains
    subroutine readtxt
""" * content * """
    end subroutine readtxt
end module m
"""

open("read_file.f90", "w") do f
    write(f, mod)
end

run(`gfortran -shared -O2 -fPIC -fconvert=big-endian read_file.f90 -o read_file.so`)

```

However, when I call the library:

```julia
ccall((:__m_MOD_readtxt, "./read_file.so"), Cvoid, ())

```

I get the error:

```julia
At line 7 of file read_file.f90 (unit = 10, file = 'RRTMG_LW_DATA')
Fortran runtime error: End of file

```

This is the same error that I get above when I don’t use `-fconvert=big-endian`, so my suspicion is that somehow that flag is not being honored when I call it from Julia. Additionally, if I use a text file instead of a big-endian binary file, calling the shared library also works fine, which further supports the idea that the problem has something to do with binary endianness.

Does anyone know how I can fix this? Thanks!

-Chris

---

<div class="post-metadata">

**Author:** ![ctessum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ctessum/32/19444_2.png) [@ctessum](https://discourse.julialang.org/u/ctessum)\
**Post date:** [November 15, 2020, 6:04am UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/2 "2020-11-15T06:04:06Z")

</div>

Update: I’ve figured out that I can add `,convert='big_endian'` to the file OPEN statement in the FORTRAN, but if it’s at all possible I would still like to find a way that doesn’t require editing the original fortran code. Thanks!

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [November 15, 2020, 3:20pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/3 "2020-11-15T15:20:18Z")

</div>

Maybe this helps:

[https://github.com/traktofon/FortranFiles.jl](https://github.com/traktofon/FortranFiles.jl)

---

<div class="post-metadata">

**Author:** ![stephancb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephancb/32/14243_2.png) [@stephancb](https://discourse.julialang.org/u/stephancb)\
**Post date:** [November 15, 2020, 5:53pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/4 "2020-11-15T17:53:21Z")

</div>

Perhaps the functions `ntoh` and `hton` in Base can be used. `ntoh` stands for “network to host”. Network is big endian, and host is little endian for all modern CPUs (but not some old ones, and not guaranteed for the future).

---

<div class="post-metadata">

**Author:** ![Juliet](https://avatars.discourse-cdn.com/v4/letter/j/97f17d/32.png) [@Juliet](https://discourse.julialang.org/u/Juliet)\
**Post date:** [November 15, 2020, 7:55pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/5 "2020-11-15T19:55:58Z")

</div>

Just keep in mind that `,convert='big_endian'` is a GNU Fortran extension and may not be supported by other compilers. You may want to fence it with the GNU Fortran preprocessor directive ` __GFORTRAN__ `

---

<div class="post-metadata">

**Author:** ![anowacki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/anowacki/32/17375_2.png) [@anowacki](https://discourse.julialang.org/u/anowacki)\
**Post date:** [November 15, 2020, 9:43pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/6 "2020-11-15T21:43:08Z")

</div>

Have you by any chance built the library first without the `-fconvert=big-endian`, tried to call subroutine `readtxt`, then rebuilt the library with the conversion flag and `ccall`ed it again within the same Julia session? If so, then you likely have not loaded the rebuilt library at all. Instead the original library is used, even though it has been rewritten on disk.

When using `ccall`, the first time a library function is called the library is `Libdl.dlopen`ed and a handle to that function found and saved in the background. Using `ccall` this way means you cannot then `Libdl.dlclose` that library and use a new one in the same place.

To dynamically load and unload a library, allowing for recompilation within the same Julia session, you can use the `Libdl.dlopen(::Function, library_path)` form of `dlopen` to open and then close the library, using `Libdl.dlsym` to get the function handle.

See the [section on this in the manual](https://docs.julialang.org/en/v1.5/manual/calling-c-and-fortran-code/#Closing-a-Library).

An example:

```julia
julia> # Compile a library to print '1' to stdout, to file `lib.so`

julia> using Libdl: dlopen, dlsym

julia> dlopen("lib.so") do lib
           func = dlsym(lib, :test)
           ccall(func, Cvoid, ())
       end
1

julia> # Recompile the library to print '2' to screen

julia> dlopen("lib.so") do lib
           func = dlsym(lib, :test)
           ccall(func, Cvoid, ())
       end
2

```

If you had simply done `ccall` without the `dlopen`s, both calls would have written `1` to stdout.

Once you have this working you can change your code back to `ccall`ing the function you need without `dlclose`ing the library handle.

---

<div class="post-metadata">

**Author:** ![ctessum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ctessum/32/19444_2.png) [@ctessum](https://discourse.julialang.org/u/ctessum)\
**Post date:** [November 16, 2020, 3:29pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/7 "2020-11-16T15:29:51Z")

</div>

Thanks! However, in this case the `Fortran runtime error: End of file` error causes the entire Julia session to crash every time, so I don’t think it’s an issue of not reloading the library, because I have to start a new session with every attempt.

---

<div class="post-metadata">

**Author:** ![ctessum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ctessum/32/19444_2.png) [@ctessum](https://discourse.julialang.org/u/ctessum)\
**Post date:** [November 16, 2020, 3:31pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/8 "2020-11-16T15:31:00Z")

</div>

Thanks for letting me know!

---

<div class="post-metadata">

**Author:** ![ctessum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ctessum/32/19444_2.png) [@ctessum](https://discourse.julialang.org/u/ctessum)\
**Post date:** [November 16, 2020, 3:32pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/9 "2020-11-16T15:32:14Z")

</div>

Thanks! I’m not quite ready to translate the whole thing to julia right now, but this may be useful in the future.

---

<div class="post-metadata">

**Author:** ![ctessum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ctessum/32/19444_2.png) [@ctessum](https://discourse.julialang.org/u/ctessum)\
**Post date:** [November 16, 2020, 4:04pm UTC](https://discourse.julialang.org/t/endianness-doesnt-seem-to-be-conserved-in-fortran-shared-libraries/50174/10 "2020-11-16T16:04:13Z")

</div>

So, it turns out that for gfortran shared libraries the endianness is specified at runtime, rather than at compile time. Therefore, all that needs to be done is:

```julia
ENV["GFORTRAN_CONVERT_UNIT"] = "big_endian"

```

before `ccall` and then it works correctly.

Reference [here](https://gcc.gnu.org/onlinedocs/gcc-4.2.4/gfortran/GFORTRAN_005fCONVERT_005fUNIT.html).

Thanks!
