1

I am trying to understand if it is possible to output binary from Fortran.

Specifically I have tried:

    integer(kind=1) :: a
    a = 64
    write(unit=6,form='UNFORMATTED') a

I am trying to output this variable to the standard output so one byte of value 64 would be written.

I.E. running:

$ ./my_code | od -d

would show a single byte of value 64.

Research done:

I have seen that there is the possibility to use Binary I/O. For example for Sun Fortran 95 compiler:

https://docs.oracle.com/cd/E19059-01/stud.9/817-6694/2_io.html (section 2.3)

But this is for files, not for standard output.

--

For standard output I have seen this post, but it is related to AIX and the /proc/self/fd/1 solution is not available in FreeBSD. I am interested in FreeBSD and Linux:

Write unformatted (binary data) to stdout

My questions are:

  1. Is there something in Fortran 95 or any other modern standard to allow and provision any functionality in write for this specific case?
  2. If so, which would be the syntax or at least, where can I learn more?
M.E.
  • 4,955
  • 4
  • 49
  • 128
  • 2
    Does `print '(B0)', a` meet your requirements, or are you trying to get the ASCII value of 64? – francescalus May 23 '21 at 21:29
  • I suggest to get a real standard Fotran resource (no matter if online or a paper book) instead of obscure manuals to obsolete compiler versions full of non-standard extensions. – Vladimir F Героям слава May 23 '21 at 21:51
  • The linked question contains two approaches in the accepted answer. Why did you disqualify the first one? Why should your question not actually be a duplicate of the linked one? Please note it does not contain only the accepted answer but also another answer that might work for you. That means **3 approaches** in total are offered in the linked question and the answers. Why can't they be used and **how should an approach you would like differ from them?** – Vladimir F Героям слава May 23 '21 at 22:00
  • Please note that the answers in the linked question are **not** AIX-specific and there are three ways offered there, not just the `/proc/self/fd/1` thing. Did you try them? What happened? – Vladimir F Героям слава May 23 '21 at 22:02
  • The post you link to shows two other methods apart from /proc/self/fd/1 - and it even says one works for Linux. Have you tried them? – Ian Bush May 23 '21 at 22:03
  • @VladimirF Your comment made me revisit the question and read again the solution. I thought that there were issues with the first approach. I have tried the buffer approach with one variable and it works. I still have a doubt as when I try to output a derived type (which is what I actually want) I am getting a weird reordering of the bytes that does not happen when I output just a single variable, I will edit the question to reflect this doubt. – M.E. May 24 '21 at 08:05
  • I actually think that the order of the bytes in a derived types is not respected, the compiler chooses its way. – M.E. May 24 '21 at 08:19
  • I also read from TRANSFER that it might not be work with derived types. – M.E. May 24 '21 at 08:26
  • I have tried both trying to `transfer` directly a derived type and transfering the individual fields of the derived type one by one and the second generates the expected binary output while the first does not. I will edit the question later today to reflect this as I think it might be useful for someone dealing with binary formats in Fortran. If however you still think this is a duplicate of the linked SO feel free to close the question. – M.E. May 24 '21 at 08:32
  • 2
    Please read what `SEQUENCE` and `BIND(C)` does to derived types. There is NO guarantee on the layout of the derived type components otherwise. You can ask a detailed question about this issue. Don't forget to show the code and the results. – Vladimir F Героям слава May 24 '21 at 08:33
  • Thanks that helps. Two questions about `BIND`: 1. does `BIND(C)` require a specific Fortran -I guess 2003 at least-? 2. In C I normally use the compiler directive `#pragma pack (1)` to ensure that the compiler does not try to align the struct so I have an accurate binary representation as if you were manually doing the layout. It can be also achieved by using `__attribute__((packed, aligned(1)))`. What does `BIND(C)` do in terms of alignment? – M.E. May 24 '21 at 08:38
  • I will prepare another question related to this. – M.E. May 24 '21 at 08:38
  • 1
    It is best to ask a special question. BIND(C) does the default C layout. The packed one will likely be achieved with SEQUENCE. However, it will no longer be interoperable. BIND(C) is Fortran 2003. See also https://stackoverflow.com/questions/7793511/are-there-performance-issues-when-using-pragma-pack1 The implications for SEQUENCE will be similar. – Vladimir F Героям слава May 24 '21 at 08:40
  • SEQUENCE does not seem to do anything related to packing, it seems to just ensure that the fields are stored in memory in an sequential manner. I had a derived type which contained a derived type of 6 bytes and I had to manually pad the inner derived type to 8 bytes to get it right. That shall be enough. Thanks for the link about pragma pack I was aware about the performance issues, but in very large datasets packing can save some space in disk and depending on the application that might be as relevant as performance. – M.E. May 24 '21 at 10:30

0 Answers0