I'm trying to write some functions/subroutines in a module that call another function in the same module and running into linker errors. A toy example displaying the same behavior:
!in test.f
module m1
implicit none
contains
real function mult(a, b)
real :: a
real :: b
mult = a * b
return
end function mult
real function sq(a)
real :: a, mult
sq = mult(a, a)
return
end function sq
end module m1
program main
use m1
write(*,*) sq(2.0)
end program
When I try to compile this, I run into trouble:
[christopher#archlinux metropolis]$ gfortran -ffree-form test.f
/tmp/ccpzdTLE.o: In function `__m1_MOD_sq':
test.f:(.text+0x20): undefined reference to `mult_'
collect2: error: ld returned 1 exit status
On the other hand, compiling only (gfortran -c -ffree-form test.f -Wall) runs with no complaint.
Now this looks for all the world like a compiler error---in the module it comes up with a reference to mult_ when it really ought to com up with __m1_MOD_sq---but I have a very hard time believing that this is a compiler bug rather than me doing something stupid.
DDG didn't turn up anything useful. Most of the similar problems ocurred in splitting the module off from one main file. In those cases, things worked when the module was in the same file as the program, which is not the case here. I looked at a number of pages on modules in Fortran and didn't see anything relevant.
Can anyone point me to appropriate documentation or, better yet, explain what's going on and how I can fix it?
You don't need to declare function mult in function sq, i.e., there is no need for "real :: mult". sq already "knows" about mult since it is in the same module. The interface of mult is known to sq since they are in the same module. The interface of mult and sq are known to the main program since it uses the module. Having both the module providing the interface and the declaration is confusing the compiler.
Related
The following code compiles, but I do not think that it should. As you can see, the output is garbage.
This is a minimal failing example of something that bit me hard in a large project I work on.
My question is - why does the compiler not complain? Is this a compiler limitation, or is this somehow "expected behaviour", and I've missed something?
I'm using gfortran 4.6.3.
module dataModule
integer :: datum1 = int(1)
integer :: datum2 = int(2)
end module dataModule
program moduleTest
use dataModule, only: datum1
write(*,*) "datum 1 is", datum1
write(*,*) "datum 2 is", datum2
end program moduleTest
Example output:
datum 1 is 1
datum 2 is 4.58322689E-41
Your code is at fault, not the compiler. If datum2 were use associated despite the only clause and if the explicit initialization of datum2 were ignored, then yes, that would be a naughty compiler.
The answer is much more mundane, though.
datum2 is not use associated: in the absence of implicit none it is an implicitly typed variable in the main program. The "garbage" comes from the fact that it is not defined, by initialization or assignment, before its value is referenced and that it's implicitly (default) real. The compiler isn't required to detect this mistake at compile (or run) time.
I need to create and use dynamic-link library (DLL) for Fortran application using Compaq Visual Fortran 6.6. The following code works just fine:
PROGRAM AMAIN1
IMPLICIT NONE
REAL(8):: A,B,S
A = 1D0
B = 2D0
CALL SUBRO1(A,B,S)
PRINT*, 'S = ', S
END PROGRAM AMAIN1
SUBROUTINE SUBRO1(A,B,S)
!DEC$ ATTRIBUTES DLLEXPORT :: SUBRO1
IMPLICIT NONE
REAL(8):: A,B,S
S = A + B
RETURN
END SUBROUTINE SUBRO1
The result is correct:
S = 3.00000000000000
Press any key to continue
However, if I implement the same algorithm using the module, I get inconsistent result (i.e. zero):
PROGRAM AMAIN2
USE MODUL2
A = 1D0
B = 2D0
CALL SUBRO2
PRINT*, 'S = ', S
END PROGRAM AMAIN2
MODULE MODUL2
IMPLICIT NONE
REAL(8):: A,B,S
END MODULE MODUL2
SUBROUTINE SUBRO2
!DEC$ ATTRIBUTES DLLEXPORT :: SUBRO2
USE MODUL2
S = A + B
RETURN
END SUBROUTINE SUBRO2
The result is incorrect:
S = 0.000000000000000E+000
Press any key to continue
As can be seen above, DLL contains only subprogram in both cases (SUBRO1 and SUBRO2, respectively). I have built DLL and LIB files from the visual development environment. The second case (with the use of module) represents the structure of my large source-code so I need to resolve this issue. Any advice would be greatly appreciated.
BTW, the same algorithm without using the DLL works well and gives correct result:
PROGRAM AMAIN3
USE MODUL3
A = 1D0
B = 2D0
CALL SUBRO3
PRINT*, 'S = ', S
END PROGRAM AMAIN3
MODULE MODUL3
IMPLICIT NONE
REAL(8):: A,B,S
END MODULE MODUL3
SUBROUTINE SUBRO3
USE MODUL3
S = A + B
RETURN
END SUBROUTINE SUBRO3
The result is correct:
S = 3.00000000000000
Press any key to continue
You need to add:
!DEC$ ATTRIBUTES DLLEXPORT :: A,B,S
to the module, so that the main program can see the module variables from the DLL. Otherwise A, B and S are local variables.
Edit: January 16, 2019
I was able to log in to Bakhbergen's PC and eventually figured out the problem.
In CVF 6.6C (and the later Intel compilers), when you USE a module that has a DLLEXPORT directive, that turns into a DLLIMPORT, hence my advice above. But it wasn't always this way, and the version he has doesn't have that behavior. Before that change (which my memory says I lobbied for), you had to supply a separately compiled .mod where the source had DLLIMPORT instead of DLLEXPORT. When I did this, the program worked. I don't remember exactly which update had this change.
So what he needs to do is have two versions of MODUL2.f90, one with DLLEXPORT and one with DLLIMPORT. The DLLEXPORT version gets built into the DLL. The DLLIMPORT version would just be compiled (/c) and only the .mod used, not the ,obj, when linking the main program. Messy, I know, which is why we changed it.
I am new to Fortran and trying to understand if the following is possible. My idea to structure the program is to declare the precision and variable types in one module. Then make use of those variables without declaring again the type in other modules or the main program.
module pre
implicit none
INTEGER, PARAMETER :: sp=SELECTED_REAL_KIND(6,37)
INTEGER, PARAMETER :: dp=SELECTED_REAL_KIND(15,307)
INTEGER, PARAMETER :: qp=SELECTED_REAL_KIND(33,4931)
REAL(dp), PARAMETER :: pi = 4.*ATAN(1.)
REAL(dp) :: H
REAL(dp) :: M
REAL(dp) :: KR
end module pre
Now I want to make use of all the variables in another module that contains one or more functions, such as:
module hon
use pre
implicit none
contains
function KE(H,M) result(KR)
KR = 2*PI/H/M
end function KE
end module hon
Then I use gfortran in this order:
gfortran -c mod_pre.f90
gfortran -c mod_hon.f90
Since 'module pre' is part of 'module hon' I compile in order, but gfortran shows an error.
With the code above I understand the variable types and parameters should have been included by USE; But the message I get from gfortran is that none of my variables have IMPLICIT type when I try to compile 'module hon'.
Could somebody clarify the problem or suggest a solution? I would like to avoid having my variables scattered in multiple modules.
Thanks!
In the function statement, the result(kr) says that the function result has name kr. This function result is not the same thing as the module variable kr. In particular, this function result makes inaccessible the module variable.
The function result is specific to the function itself and its properties must be declared within the function subprogram.
Similarly, the dummy arguments of the function, H and M, are distinct from the module variables and need to be declared in the function subprogram.
Beyond that, you perhaps have similar concerns to this other question.
To be clear, it isn't possible to say something like "all function results called kr and all dummy arguments called H or M have these characteristics". Each individual object must be given the properties.
However, although I don't recommend this, this is a situation where literal text inclusion (using a preprocessor or include file) could help you:
function ke(H, M) result (kr)
include 'resdummydecls'
...
end function
where the file has the declarations.
How to call C DLL from Fortran? I don't code in Fortran but I need to do some testing on it.
Let say in the test.dll have functions:
Open()
Close()
How can I tell Fortran to use the test.dll?
I mean like C# we may use
[DllImport("test.dll")]
static extern uint Open();
I could not find any example that can help me. I would also prefer if you could provide a compiler that you use.
Update
I use Plato compiler.
I tried to load test.dll using this method. However, it popped up error message saying Error 29, Call to missing routine: _LOADLIBRARY
Here is the code. I found it online. So not sure if I'm doing it correctly.
program test
integer :: p
pointer :: q
p = loadlibrary ("test.dll"C) ! the C at the end says -
! add a null byte as in C
q = getprocaddress (p, "Open"C)
end
EDIT
Sorry. The DLL is using C and not C++
i have a module 'gvars' defined for my global variable declarations. when i define
integer :: nthreads, max_threads, tid, omp_get_max_threads, omp_get_num_threads, omp_get_thread_num inside of my gvars module, the call maxthreads = omp_get_max_threads() in my main routine gives me the following error upon compilation:
maxthreads = omp_get_max_threads()
1
Error: Unclassifiable statement at (1)
but when i include the integer :: definitions above inside my main routine, it compiles just fine and gives me the desired results. if i even go as far as to define nthreads = -1 inside my gvars module, i am able to print out the correct value in my main routine so i know it is being included and defined correctly, it's just that for some reason i cannot have it as a return value from openmp functions.
why would this be?
is there any other way to keep these values as global variables and still define them in my main routine instead of a module?
if it matters, i am using gfortran to compile
The problem is not with the declaration of maxthreads, but with the declaration, on the same line, of omp_get_max_threads. As haraldkl showed, you need to use omp_lib instead, to automatically get access to the declarations of these functions.
(If for some reason you really don't want to do it that way, you can also add the statement external :: omp_get_max_threads, ... to the module.)
Not really an answer, but I do not know how else to put the code in here. Sorry...
module gvars
integer :: maxthreads
end module gvars
program test
use gvars
use omp_lib
implicit none
maxthreads = omp_get_max_threads()
end program test
compiled with:
gfortran -fopenmp test.f90
Where gfotran -v gives:
gcc version 4.4.5 (GCC)