I have something like
integer a
integer b
b = 0
integer c
a = 0
c = 0
which does not work with the error
"A specification statement cannot appear in the executable section."
However, changing it to
integer a
integer b
integer c
a = 0
b = 0
c = 0
works.
Yes, this is forbidden in Fortran. This is defined in the Fortran 2008 Standard, Cl. 2.3.2 "Statement order":
1 The syntax rules of clause 2.1 specify the statement order within program units and subprograms. These rules
are illustrated in Table 2.1 [...]. Table 2.1 shows the ordering rules for statements and applies to
all program units, subprograms, and interface bodies. Vertical lines delineate varieties of statements that may
be interspersed and horizontal lines delineate varieties of statements that shall not be interspersed. [...] Between USE and CONTAINS statements in a
subprogram, nonexecutable statements generally precede executable statements [...]
(Emphasis mine)
[Slightly off-topic, but related] Please note that while
integer :: a
integer :: b = 0
integer :: c
is allowed, this has the side effect that b gets the save attribute. That is typically not what you want...
The error message is quite clear. Fortran programs and subprograms are divided into two parts. First the specification part where you use modules, define variables, derived types, interfaces... And then the executable part where you put the actual executable statements or control structures.
It is not possible to mix them.
The situation is murkier in f2008, with the BLOCK construct. That construct necessarily lies among the executable statements, but is often there for the sole purpose of adding the capability to place some specification statements after executable statements, as when an assumed length pointer is to be pointed at anonymous memory.
EDIT: Example
module anonymous
use ISO_C_BINDING
implicit none
interface
function malloc(size) bind(C,name='malloc')
import
implicit none
type(C_PTR) malloc
integer(C_SIZE_T), value :: size
end function malloc
subroutine free(ptr) bind(C,name='free')
import
implicit none
type(C_PTR), value :: ptr
end subroutine free
function strlen(str) bind(C,name='strlen')
import
implicit none
type(C_PTR), value :: str
integer(C_SIZE_T) strlen
end function strlen
end interface
contains
function hello()
type(C_PTR) hello
character(LEN=*,KIND=C_CHAR), parameter :: world = &
'Hello, world'//C_NULL_CHAR
character(LEN=len(world),KIND=kind(world)), pointer :: fptr
hello = malloc(len(world,KIND=C_SIZE_T))
call C_F_POINTER(hello,fptr)
fptr = world
end function hello
end module anonymous
program test
use anonymous
implicit none
type(C_PTR) cptr
character(LEN=:,KIND=C_CHAR), pointer :: fptr
integer(C_SIZE_T) hello_len
cptr = hello()
hello_len = strlen(cptr)
BLOCK
character(LEN=hello_len,KIND=C_CHAR), pointer :: temp
call C_F_POINTER(cptr,temp)
fptr => temp
end BLOCK
write(*,'(*(g0))') fptr(1:strlen(cptr))
end program test
Related
I am trying to call some Fortran code from C but I didn't find the proper way of passing a C char array.
SUBROUTINE My_F_Code (c_message) BIND(C, NAME='my_f_code')
USE ISO_C_BINDING
IMPLICIT NONE
CHARACTER*(C_CHAR) c_message
CHARACTER*(256) f_message
CALL C_F_POINTER( C_LOC(c_message), f_message)
WRITE(*,*) f_message,LEN(f_message)
END
The BIND(C) force the parameter c_message to be size 1. How can I access to other elements of the c_message string?
Compiler : GCC 4.8.2
I am trying to call some Fortran77 code from C but I didn't find the proper way of passing a C char array.
All Fortran 77 implementations I've ever used have afforded implementation-specific mechanisms for interoperation with C. Generally these involve the C side knowing the name-mangling and argument-passing conventions employed by the Fortran compiler, and using them at the interface. The GCC system's conventions are not that hard to use.
You seem to be interested in the Fortran/C interop facility introduced in Fortran 2003, however. Supposing that your Fortran 77 code also conforms with Fortran 2003 (or can be made to do so), it should be possible to write an interoperable wrapper in Fortran 2003. Be aware, however, that the C interop facility does not provide (directly) for interoperability of Fortran variables or subprogram parameters of type character with length greater than 1 or kind different from c_char. On the other hand, keep also in mind that the length of a Fortran character object is not the same thing as the dimension(s) of a character array.
You have a couple of interoperable alternatives for providing a C-facing interface by which to accept a C char array. Perhaps the clearest one would be to accept a Fortran assumed-size character array:
SUBROUTINE My_F_Code (c_message) BIND(C, NAME='my_f_code')
USE ISO_C_BINDING
IMPLICIT NONE
CHARACTER(kind=C_CHAR), dimension(*), intent(in) :: c_message
! ...
END
The most likely alternative is to accept C's array pointer directly:
SUBROUTINE My_F_Code (c_message) BIND(C, NAME='my_f_code')
USE ISO_C_BINDING
IMPLICIT NONE
type(C_PTR), value :: c_message
! ...
END
The latter is necessary if the C-side array pointer might be null. Both require an explicit length to be passed as well if the array cannot be relied upon to be null terminated.
In any event, if you ultimately want a Fortran character variable having length greater than 1 (as opposed to an array having dimension greater than 1), then the interoperable interfaces can't provide that directly -- such types are not among those to which the C interop provisions are applicable. Unless you can rely on the default character kind to be c_char, you'll need to couple them with copy-in(/ copy-out) in order to convert the characters between kinds. With the former interface, it should be obvious how you could copy the array to a Fortran scalar character having length greater than 1. For the pointer variant, it might be useful to use a conversion function something like this:
subroutine C_string_ptr_to_F_string(C_string, F_string)
use ISO_C_BINDING
type(C_PTR), intent(in) :: C_string
character(len=*), intent(out) :: F_string
character(len=1, kind=C_CHAR), dimension(:), pointer :: p_chars
integer :: i
if (.not. C_associated(C_string)) then
F_string = ' '
else
call C_F_pointer(C_string, p_chars, [huge(0)])
do i = 1, len(F_string)
if (p_chars(i) == C_NULL_CHAR) exit
F_string(i:i) = p_chars(i)
end do
if (i <= len(F_string)) F_string(i:) = ' '
end if
end subroutine
(Derived from the Fortran Wiki's C_interface_module's C_F_string_ptr subroutine)
On the other hand, if you can (or anyway do) rely on the default character kind to be c_char then you have an additional alternative. You can usefully cause a character array such as the parameter in the first example to be associated with a scalar character object of default kind and length greater than one. In particular, if a dummy argument of the wrapped function is a scalar character with assumed length, or with fixed length not exceeding the number of array elements, then you can rely on argument association to associate it with the character array in the wrapper. In other words, in that case you can just pass the array as the actual argument.
SUBROUTINE FCODE(STR, N)
CHARACTER*(*) STR
INTEGER N
WRITE(*,*), STR, N
END
void foo(char *str)
{
int N = 10;
printf("Calling fortran\n");
fcode_(str, &N, strlen(str));
}
You need to pass sgtring length as a hidden parameter.
See my article here
http://www.malcolmmclean.site11.com/www/MpiTutorial/CandFortran77.html
Say we have the following code:
module foo
use :: iso_fortran_env
implicit none
type :: bar (p, q)
integer, kind :: p
integer, len :: q
integer(kind = p), dimension(q) :: x
end type bar
contains
subroutine barsub (this)
class(bar(*,*)), intent(in) :: this
write (*,*) this%x
end subroutine barsub
end module foo
This code does not compile with either gfortran 8 or pgfort 18.4. The pgi compiler says
Illegal selector - KIND value must be non-negative
Assumed type parameter (*) cannot be used with non-length type parameter p
whereas gfortran yields
The KIND parameter 'p' at (1) cannot either be ASSUMED or DEFERRED
If I change above code to
subroutine barsub (this)
class(bar(INT32,*)), intent(in) :: this
write (*,*) this%x
end subroutine barsub
it compiles fine with both compilers.
Is it possible to write a subroutine where the kind parameter does not need to be specified explicitly? In the example above, the code would be the same for INT32, INT64, ... and I don't want to copy paste it for every imaginable value of the kind parameter. It works fine for the len parameter. Why can't I do the same with the kind parameter?
Is it possible to write a subroutine where the kind parameter does not need to be specified explicitly?
No, kind type parameters need to be given by a constant expression or defaulted, see, e.g., the Fortran 2008 standard, definition 1.3.147.12.3.
Why can't I do the same with the kind parameter?
The fact that len and kind type parameters have different uses and requirements is the point of having two types of type parameters, if their characteristics were the same we wouldn't need two of them.
Note that procedures require of the kind parameters of their dummy arguments of parameterized derived types just same they require of the kinds of their dummy arguments of intrinsic types: to have their values defined at compilation time.
In response to a question about character function results of non-constant length, an answer mentions "assumed length function result" but doesn't go into detail.
If I want to return a character result where the length depends on something else, that answer mentions automatic objects and deferred length as possible approaches:
function deferred_length(x)
character(*), intent(in) :: x
character(:), allocatable :: deferred_length
deferred_length = x//'!'
end function
or
function automatic(x)
character(*), intent(in) :: x
character(LEN(x)+1) :: automatic
automatic = x//'!'
end function
What is an assumed length function result and how does it differ from the forms above? Further, why is such mention relegated to a footnote?
An assumed length character function looks like the following:
function assumed_len(x)
character(*), intent(in) :: x
character(*) :: assumed_len
assumed_len = x//'!'
end function
Here the dummy argument x and the function result assumed_len are both assumed length characters.
Much like how x assumes its length from the actual argument when the function is referenced, the function result assumes its length from the function declaration in the referencing place.
With the above function, consider the program
implicit none
character(len=11) :: x='Hello world'
character(len=12) assumed_len
print *, assumed_len(x)
end
During the function's execution the function result has length 12 as declared in the main program. Equally, if we wanted it to have length 5 we simply change the declaration in the main program to character(len=5) assumed_len. In a different program unit the declaration could be something different and the function result would assume that length when referenced.
Well, that doesn't look so harmful: why should we avoid using functions like this?
In summary:
They go against the "philosophy" of modern Fortran.
There are better ways in modern Fortran to accomplish the same thing.
They are quite limited.
In every other aspect of Fortran, the attributes of a function result depend only on the arguments of the function and other accessible information. Here the attributes of the function result may differ with everything else the same through a declaration in an unrelated scope.
To the other points:
the interface of such a function must be implicit in a referencing place (and we don't like implicit interfaces);
we can't reference the same function twice in one place and get different length results, even with differing input;
the function has a much better idea of what length it wants to return.
In those cases where we really do want to control the length in the referencing place we can replace assumed_len with a function with explicit length result like
function replacement(x, n)
character(*), intent(in) :: x
integer, intent(in) :: n
character(n) :: replacement
...
end function
or a subroutine with assumed length dummy argument
subroutine replacement(x, y)
character(*), intent(in) :: x
character(*), intent(out) :: y
...
end subroutine
Finally, assumed length character functions are declared obsolescent in the current Fortran standard, and may be deleted in later revisions.
I have a simple question regarding derived types and allocated arrays.
Suppose we have defined the type
type demo_type
real(kind=8),allocatable :: a(:)
end type demo_type
and the function
function demo_fill(n) result(b)
integer, intent(in) :: n
real(kind=8) :: b(n)
b = 1.d0
end function demo_fill
Is it correct to write in the main program
type(demo_type) :: DT
DT%a = demo_fill(3)
Or is it necessary to first allocate DT%a to prevent accidentally overwriting other variables in memory?
type(demo_type) :: DT
allocate(DT%a(3))
DT%a = demo_fill(3)
They both compile, but I am wondering which is the correct way. Thanks!
In Fortran 2003 any allocatable array can be allocated automatically on assignment.
In your case
DT%a = demo_fill(3)
causes DT%a to be automatically allocated to the shape of the right hand side, which is the result of the function, if it has not been allocated to this shape previously.
This behavior is standard, but some compilers do not enable it by default, notably the Intel Fortran. You must use special compiler flags to enable it (-standard-semantics, -assume realloc_lhs)
As a side note, kind=8 does not mean 8-byte reals on all compilers, and this usage is frowned upon (see https://stackoverflow.com/a/856243/721644).
Why is it that Fortran will promote a scalar expression to an array, in an expression, but not as an argument to a procedure? In particular, why did the standards body make this design decision? Is it solely because of ambiguity, should the procedure be overloaded? Could an error message in that situation be an alternative approach?
For example, In the code below, the last statement, x = foo(7), produces the GFortran error: Error: Rank mismatch in argument 'a' at (1) (1 and 0).
module m
public :: foo
contains
function foo(a) result(b)
integer, dimension(:) :: a
integer, dimension(size(a)) :: b
b = a+1
end function foo
end module m
program p
use m
integer, dimension(4) :: x
integer, parameter, dimension(4) :: y = (/1,2,3,4/)
x = 7
x = foo(x)
x = foo(y)
x = foo(x + 7)
x = foo(7)
end program p
This question should have asked about why an array assignment will promote a scalar value source to an array target; unlike an array function. I expect that's simply a convenient special case though. Any comments gratefully received in the begging caps below.
If you want the function to handle scaler and array arguments, declare it as "elemental" and with scaler dummy arguments. Then it will be able to handle both scaler and array actual arguments, including scaler expressions. Will that meet your need?
The change:
elemental function foo(a) result(b)
integer, intent (in) :: a
integer :: b
b = a+1
end function foo
Perhaps they provided a way to do what you want, and one way was enough?
Procedure calling in Fortran with explicit interfaces (which you get automatically when using module procedures) requires a TKR (type, kind, rank) match. As an array is a different type than a scalar, not to mention the rank mismatch, this is not allowed.
Is it because of ambiguity should the procedure be overloaded?
That would be a problem, yes.
Could an error message in that situation be an alternative approach?
Could pink unicorns exist? Maybe, but to the best of my knowledge they don't. IOW, the Fortran standard currently requires TKR matching, and thus a standard conforming compiler must enforce this requirement. If you want to change that, I recommend making a proposal to the standards committee.
I would think the answer to this is pretty clear. Let's slightly modify your example:
module m
public :: foo
contains
function foo(a) result(b)
integer, dimension(:) :: a
integer, dimension(size(a)) :: b
b = a+1
a(2) = -777 ! new line; modify one element
end function foo
end module m
program p
use m
integer :: x
integer, dimension(4) :: y
x = 7
y = foo(x) ! pass a scalar
end program p
what is x supposed to be after the call to foo?
Now, sure, you could have the semantics of argument passing change depending on whether or not it's an intent(in) variable, but that is not something which is going to clarify things for programmers.
If the function call is supposed to 'distribute' somehow over array elements, then as MSB points out, elemental is the way to go. Otherwise, one just makes sure one's arguments match one's parameters.