On 08/13/2012 01:20 PM, Paweł Biernat wrote:
> W dniu poniedziałek, 13 sierpnia 2012 10:50:34 UTC+2 użytkownik Paul Anton Letnes napisał:
>> So the Fortran question is: Is there a good and clean way to include
>>
>> long character literals (aka strings) in the compiled code? I'm thinking
>> perhaps 50-100 lines of Lua code, some to be run before running the
>> input file to the simulation code, and some to be run after the input
>> file. I want the files to be included in the statically linked binary,
>> simply for convenience.
Well, you could simply use something like:
character(len=*), parameter :: str = 'Hel&
lo Wor&
&ld!'
print *, str
end
That is: A single string literal. To be conforming, the lines should be
maximally 132 characters (or 72 in fixed form) long. I think Fortran <=
95 limits the number of continuation lines to 19 (fixed form) and 39
(free form source code), which was extended to 255 in Fortran 2003 and
later. I think many compilers happily accept more, some (like gfortran
with -std=f95/f2003) warn, and others simply reject (without having a
special flag).
Note: The example above uses a Fortran 2008 feature: the "len=*". In
Fortran 95/2003, you need to calculate yourself the number of characters.
> There is a pretty neat way of doing this in C:
>
http://burtonini.com/blog/computers/ld-blobs-2007-07-13-15-50
>
> I am trying to make it work with Fortran using iso_c_binding but there are some memory alignment problems and I have no knowledge to resolve them. Maybe someone more resourceful will be able to help with it.
The following not very elegant code works here. I do get alignment
warnings, but one can ignore them.
I also don't get an scalar character string but an array of len=1
strings. One can surely make the code nicer. A brute force method would
be "cstr_start(1:len)" but that's not really nicer. One could also think
about copying the data to a scalar character string of the proper
length, but that duplicates the data.
Tobias
$ echo 'Hello Fortran World!' > foo.txt
$ ld -r -b binary -o foo.o foo.txt
$ gfortran -g fortran.f90 foo.o && ./a.out
/usr/bin/ld: Warning: alignment 1 of symbol `_binary_foo_txt_end' in
foo.o is smaller than 8 in /tmp/ccX0oFRi.o
/usr/bin/ld: Warning: alignment 1 of symbol `_binary_foo_txt_start' in
foo.o is smaller than 8 in /tmp/ccX0oFRi.o
22
Hello Fortran World!
$ cat fortran.f90
module m
use iso_c_binding
implicit none
character(c_char), bind(C, name='_binary_foo_txt_start'), target ::
cstr_start
character(c_char), bind(C, name='_binary_foo_txt_end'), target :: cstr_end
end module m
use m
implicit none
character(len=1, kind=c_char), pointer :: str(:)
type(c_ptr) :: cptr
integer(c_intptr_t) :: len
len =transfer(c_loc(cstr_end),len) - transfer(c_loc(cstr_start),len) + 1
print *, len
call c_f_pointer (c_loc (cstr_start), str, shape=[len])
print '(*(a))', str
end