Let's assume I have the following code:
module eval_mod
implicit none(type, external)
private
public :: eval
abstract interface
real pure function real_function_t(x)
real, intent(in) :: x
end function
end interface
contains
pure function eval(f, x) result(res)
procedure(real_function_t) :: f
real, intent(in) :: x
real :: res
res = f(x)
end function
end module
program main
use iso_fortran_env, only: stdout => output_unit
use eval_mod, only: eval
implicit none(type, external)
write(stdout, *) eval(double, 2.)
write(stdout, *) eval(triple, 2.)
contains
pure real function double(x)
real, intent(in) :: x
double = 2. * x
end function
pure real function triple(x)
real, intent(in) :: x
triple = 3. * x
end function
end program
and compile it with gfortran -Wall -Wextra -Werror -g -fbounds-check.
If I set a breakpoint to eval_mod::eval, I would like to see with which function argument eval was called.
What I actually see is
Breakpoint 2, eval_mod::eval (f=0x7fffffffced8, x=2) at main.F90:17
If I take the address and follow this question, I should be able to see the function name in the symbol table by doing:
info symbol 0x7fffffffced8
Unfortunately I get an error
No symbol matches 0x7fffffffced8.
How can I see the function name of a function passed as argument?
PS: I use gfortran 7.5.0 and gdb 11.1.
double and triple are internal functions (inside the main program). Passing internal functions is tricky due to the host association of the variables from the parent scope. Therefore they are often implemented using trampolines. The address you see is the address of the trampoline, in other words, a so called thunk. The trampoline than calls the actual function.
The address most likely points somewhere on the stack where the trampoline code is placed. In that code you will likely find a jump instruction with the address of the actual function.
See also this great article by Steve Lionel Doctor Fortran in “Think, Thank, Thunk”
Related
I wrote a fortran function to call a blas level 3 function sgemm. I'm passing the matrices to be multiplied to this function and returning the result. The code works and the result is also correct. But there is a print statement inside which won't print anything. Why is that happening?
function matmul(A,B) result(C)
real,dimension(:,:),allocatable::A
real,dimension(:,:),allocatable::B
real,dimension(:,:),allocatable::C
integer::m,n,k
m = size(A,1)
n = size(A,2)
k = size(B,2)
print *,"INSIDE FN"
call sgemm ('N','N',m,k,n,1.0,A,n,B,k,0.0,C,k)
end function matmul
The function name you chose, MATMUL, is a fortran intrinsic function (see section 13.7.105 of the fortran standard or here). The function you implemented tries to 'overload/shadow' this intrinsic with the same name. This is possible in Fortran, but you have to explicitly inform the compiler about it. When compiling the following code :
function matmul(A,B) result(C)
real,dimension(:,:),allocatable::A,B,C
print *,"matmul overloaded"
C=A
end function matmul
program test
real, dimension(:,:), allocatable :: A,B,C
allocate(A(1,1),B(1,1),C(1,1))
C = matmul(A,B)
end program test
The program test has no knowledge about the existence and/or interface of your own matmul subroutine. Both the program test and the subroutine matmul live in two unconnected program units, and as a consequence, the compiler will assume that the intrinsic MATMUL function is to be called.
EXTERNAL attribute: (see STDF2003::5.3.9)
As the compiler has no mechanism to access the users matmul code from the program unit test, it's interface is implicit. If you want to specify that the name matmul is the one of an external or dummy procedure, we can use the external statement :
program test
external :: matmul
real, dimension(:,:), allocatable :: A,B,C
allocate(A(1,1),B(1,1),C(1,1))
C = matmul(A,B)
end program test
INTERFACE block : (See STDF2003::12.4)
With the external attribute, you just specify that matmul is an external or dummy procedure. It does not specify the interface, which remains implicit. The interface, however, can be defined by means of an interface block as
program test
real, dimension(:,:), allocatable :: A,B,C
allocate(A(1,1),B(1,1),C(1,1))
interface
function matmul(A,B) result(C)
real,dimension(:,:),allocatable::A,B,C
end function matmul
end interface
C = matmul(A,B)
end program test
The latter is automatically achieved when placing the function matmul in a module and using that module.
note: information loosely adopted from Modern Fortran Explained, M. Metcalf, J. Reid and M. Cohen, (Oxford, 2013)
I am migrating from ifort14 to ifort16, on 14 the code compiles and runs fine on 16 I get a compile time error which makes no sense to me. Long story short the compiler complains about a procedure whose definition is the last in the file and if I change the order it will complain about a different procedure, again the one that comes last. The error does not make any sense and this behaviour does not make sense either. Does this sound familiar to someone and do you have any idea where I could look for the problem?
I have the following structure
File1:
module model_generic
implicit none
type, abstract :: modelGen
logical, public :: init_flag = .false.
contains
procedure :: isInit => dispInitFlag_model
procedure, nopass :: taylorRule_func
procedure, nopass :: penalty_func
end type modelGen
contains
function dispInitFlag_model(this) result(init_flag)
class(modelGen), intent(in) :: this
logical :: init_flag
init_flag = this%init_flag
end function dispInitFlag_model
end module model_generic
File2:
module model_nk_generic
use model_generic
implicit none
type, abstract, extends(modelGen) :: model_nk
logical, public :: init_flag_nk = .false.
contains
procedure :: isInit => dispInitFlag_model_nk
procedure :: setIniGuess => setIniGuess_model_nk_default
! deferred procedures
procedure(obj_func), deferred :: lossFunction
procedure(IS_PC_curves), deferred :: IS_PC0
procedure(Taylor_IS_PC_curves), deferred :: taylor_IS_PC
procedure(IS_curve), deferred :: IS
procedure(PC_curve), deferred :: PC
procedure(R_trans), deferred :: R_lom
procedure(A_trans), deferred :: A_lom
procedure(eps_trans), deferred :: eps_lom
generic :: IS_PC => IS_PC0, taylor_IS_PC
end type model_nk
abstract interface
! omitted
end interface
contains
function dispInitFlag_model_nk(this) result(init_flag_nk)
class(model_nk), intent(in) :: this
logical :: init_flag_nk
init_flag_nk = this%init_flag_nk
end function dispInitFlag_model_nk
subroutine setIniGuess_model_nk_default(this,VFonGrid,grid)
class(model_nk), intent(in) :: this
real(KIND=DP), dimension(:), intent(out) :: VFonGrid
real(KIND=DP), dimension(:,:), intent(in), optional :: grid
VFonGrid = 0e0
!VFonGrid = 1._DP
end subroutine setIniGuess_model_nk_default
end module model_nk_generic
The error I receive during compilation (the above is compiled as a part of a bigger project) is
error #8437: The type/rank signature for the arguments of this specific
subroutine matches another specific subroutine that shares the same
ASSIGNMENT generic binding.
end subroutine setIniGuess_model_nk_default
^
The procedure (or its binding name) does not appear anywhere else in the programme except one module where it is called (I grepped for it to be sure). Thus it cannot share any generic binding. When I delete it the compiler gives me the same error with the dispInitFlag_model_nk procedure. When I add a do_nothing procedure then it will complain about that one. The compiler seems to always complain about the last procedure in the file.
A minimalistic test case like below compiles fine (using the same makefile). Another code without any OOP features compiles fine too.
program main
use model_generic
use model_nk_generic
class(model_nk), allocatable :: svars
end program main
Every time I do a clean compilation, all libraries that I use I compile from source except MKL but that should be linked correctly I have checked that.
Does any one have any idea what could be wrong with the source file or with my compiling environment?
Edit1: Forgot to mention the compiler flags. Normally I use ifort -openmp -O3 but I also tried my usual set of debugging flags ifort -openmp -g -p -traceback -check bounds -ftrapuv -fpe0 -O0 -warn -check uninit -gen-interfaces -warn interfaces -check all and I tried with and without the -openmp flag. At some point the compiler told me the flag was deprecated but using -qopenmp instead did not change things.
Edit2: Probably I should also have mentioned that I also use the preprocessor. And both files are preprocessed. But again on v14 it works fine and the error occurs in file2 after file1 (its dependency) is compiled.
I'm just beginning with Fortran, and I've got a program and a function
PROGRAM multiplication
implicit none
real :: A1
!A1 = mult(2, 3)
!write(*,1) A1
1 format(f8.8)
END PROGRAM multiplication
REAL FUNCTION mult(a, b) BIND(C, name='foomult')
real,value :: a,b
mult = a * b
END FUNCTION
I've got the function working in java through JNA, but when I try to call mult from within the fortran main program, I get a ton of compiling errors (I can provide them if you want). I have a feeling it must be something obvious but I can't find a solution anywhere. Are bound functions not intended to be called from within non-external code? Or do I just have a poor understanding of function syntax?
For the main program, the compiler doesn't "know" the properties of the function, i.e., the types of the function and its arguments. Your function uses an "advanced" argument property, value, so it is necessary to declare the properties in some way to the caller. The easiest way to make those properties known to the caller is to put the function into a module and use that module from a program or procedure that uses it:
module MyModule
contains
FUNCTION mult(a, b) BIND(C, name='foomult')
use iso_c_binding
real (c_float) ,value :: a,b
real (c_float) :: mult
mult = a * b
END FUNCTION
end module MyModule
PROGRAM multiplication
use MyModule
implicit none
real :: A1
A1 = mult(2.0, 3.0)
write(*,*) A1
END PROGRAM multiplication
I've also declared the variables in the function to be compatible with C. It happens, at least with gfortran on my computer, that those are the same as plain real, so they are compatible with the call in the main program. Compatibility could be guaranteed by writing the call as mult (2.0_c_float, 3.0_c_float).
Well, this is the issue I've today...
I'm writing a module procedure that has, as an argument, a function. This module looks something like this:
module Integ
implicit none
<variables declaration>
contains
function Integral(a,b,f) result(res)
real, intent(in) ::a, b
real ::res
interface
pure function f(x)
real, intent(in) :: x
real :: f
endfunction
endinterface
<more code of function Integral>
endfunction Integral
endmodule Integ
Well, up to here, everything is great. The issue appears when I try to use this function with a Fortran intrinsic function. I.e., in this code:
program main
use Integ
implicit none
real ::res,a,b
a=3.0; b=4.0
res=Integral(a,b,sin) !<- This line does not work
!res=Integral(a,b,sen) !<- This line does work
contains
function sen(x)
real, intent(in) :: x
real :: sen
sen=sin(x)
endfunction
endprogram
The first line does not work, giving the error message:
main.f90(17): error #6404: This name does not have a type, and must have an explicit type. [SIN]
r=Int1DMonteCarlo(0.0,1.0,sin,10000)
--------------------------^
main.f90(17): error #6637: This actual argument must be the name of an external user function or the name of an intrinsic function. [SIN]
r=Int1DMonteCarlo(0.0,1.0,sin,10000)
--------------------------^
But the second line (comented in the snipplet) does.
Those errors are quite disorienting for me, because sin is a Fortran intrinsic function (thing that contradicts error nr 2), and in consequence explicit in every scope (thing that contradicts the error nr 1).
Obviously I'm doing something wrong but I don't know what.
So I would like to ask:
It is possible to call a module procedure with an intrinsic function as an actual argument?
I'm loosing something aside from declaring the interface inside the procedure?
If you are interested this is the complete source of the module and this is the source of the main
Sorry if I'm asking a stupid question. I think I am doing things the way the books I'm reading now (Metcalf, Numerical recipes for Fortran V:II) are telling me.
Thank you for your time!
Use an intrinsic statement in the main program to declare that the actual argument sin is the intrinsic. This requirement is spelled out in the description of the intrinsic attribute in the Fortran standard.
With an eye to the future, you may be better off writing your own wrapper function around the intrinsic - create a function mysin that simply calls sin.
I was quite happy with the construct that worked well with gfortran until I tried it with ifort. Though I have not ever seen it clearly documented. I just tried that and it worked. I'm curious though how could I adjust the following sample such that ifort 11.1 can chew it.
module A
use iso_c_binding
implicit none
interface
function foo(x) bind(C, name="strlen")
use, intrinsic :: iso_c_binding
character(c_char), intent(in) :: x
integer(c_size_t) :: foo
end function foo
end interface
end module A
module B
use A
! use A, foo0 => foo
implicit none
interface foo
module procedure foo1
procedure foo
end interface foo
contains
function foo1(x)
real, intent(in) :: x
real :: foo1
foo1 = 2. * x
end function foo1
end module B
program C
use B
implicit none
write (*,*) foo(C_CHAR_"Hello" // C_NULL_CHAR)
write (*,*) foo(2.)
end program C
Here is an error message I'm getting
tst.f90(20): error #6643: This statement is incorrectly positioned.
procedure foo0
-----^
tst.f90(20): error #8168: Parentheses are required after the PROCEDURE keyword.
procedure foo0
-----^
Is it a GNU extension? -pedantic does not complain. It works as I expect it to work
5
4.00000000
Do I have to write in full details foo0 declaration inside of interface foo?
UPDATE 2013-03-31
I adjusted example code above to include bind(C). Since it resides in interface, I cannot use module even with gfortran. I apologize for misleading with improper trimmed down example previously.
Another update 2013-03-31
Apparently ifort version 13.1.1 does not support such constructs (no matter if I rename foo to foo0 or not)
tst.f90(22): error #6623: The procedure name of the INTERFACE block conflicts with a name in the encompassing scoping unit. [FOO]
procedure foo
---------------^
tst.f90(22): error #8574: A procedure-name in a generic interface block must be a nonintrinsic procedure that has an explicit interface. [FOO]
procedure foo
---------------^
If I add module before procedure, I get
tst.f90(22): error #7950: Procedure name in MODULE PROCEDURE statement must be the name of accessible module procedure. [FOO]
module procedure foo
----------------------^
It looks like it is not currently possible to do what I want unless I explicitly declare that bind(C) interface again in all details :(
It is a Fortran 2003 feature:
"When MODULE is specified, procedure-name_list can only contain module procedures. When MODULE is not specified, procedure-name_list may contain procedure pointers, external procedures, dummy procedures, or module procedures."
Your version 11.1 is obsolete, current release is 13, but I am not sure if it is supported now.
In this case it should be OK to use module procedure until your versions of compilers support Fortran 2003 fully:
"If the MODULE keyword appears, each procedure name has to be a module procedure and has to be accessible in the current scope."
source: IBM XL Fortran manual
With foo a C-function, it seems that foo can't be a module procedure. An intermediate function can be used as a workaround:
module A
use, intrinsic :: iso_c_binding
implicit none
interface
function strlen(x) bind(C, name="strlen")
use, intrinsic :: iso_c_binding
character(kind=c_char, len=1), dimension (*), intent(in) :: x
integer(c_size_t) :: strlen
end function strlen
end interface
contains
function foo (x)
character(kind=c_char, len=*), intent(in) :: x
integer (c_size_t) :: foo
foo = strlen (x)
end function foo
end module A
module B
use A
! use A, foo0 => foo
implicit none
interface foo
module procedure foo1
module procedure foo
end interface foo
contains
function foo1(x)
real, intent(in) :: x
real :: foo1
foo1 = 2. * x
end function foo1
end module B
program C
use B
implicit none
write (*,*) foo(C_CHAR_"Hello" // C_NULL_CHAR)
write (*,*) foo(2.)
end program C