unable to Find Entry point Fortran Dll - visual-studio-2010

Continuing the last unsolved question about dll, i tried to create fortran dll using g95 with following commands:
g95 -c FCall.f90
g95 -shared -mrtd -o FCall.dll FCall.o
When I linked it to VB, It shows "Unable to find an entry point named 'FortranCall' in DLL 'C:\Users\Hp\Documents\Visual Studio 2010\Projects\WindowsApplication5\WindowsApplication5\FCall.dll'."
Here's the FORTRAN code:
SUBROUTINE FortranCall (r1, num)
!DEC$ ATTRIBUTES DLLEXPORT :: FortranCall
!DEC$ ATTRIBUTES ALIAS:'FortranCall' :: FortranCall
REAL,INTENT(IN) :: r1
REAL,INTENT(OUT) :: num
num = MOD (r1, 256.0)
END SUBROUTINE
Here's the VB code:
Private Sub Command1_Click()
r1 = 456.78
Call FortranCall(r1, Num)
Text1.Text = Str$(Num)
End Sub
Module code in VB:
Declare Sub FortranCall Lib"C:\Users\Hp\Documents\Visual Studio 2010\Projects\WindowsApplication5\WindowsApplication5\FCall.dll"
(r1 As Single, Num As Single)
Is G95 has own export statement to export function from dll ?
in this subroutine, the export attribute (!DEC$ ATTRIBUTES DLLEXPORT :: FortranCall) was used in visual fortran

The directives you use is a highly compiler specific thing. Even the name suggest it is specific to the DEC compiler (and descendants - Compaq and Intel).
Gfortran has the same thing, but with !$GCC, but not G95.
I highly recommend you to use the Fortran 2003 feature bind(C,name="name") instead to set the symbol name. See also the tag https://stackoverflow.com/questions/tagged/fortran-iso-c-binding.
SUBROUTINE FortranCall (r1, num) bind(C,name="FortranCall")
!DEC$ ATTRIBUTES DLLEXPORT :: FortranCall
END SUBROUTINE
Both GCC and G95 export the symbols by default then, no need for the dllexport directive, but leave it there for the Intel Fortran.
Alternatively, you can try the option -fno-underscoring, but that is again specific to g95 and will not work with other compilers.

Related

"Can't open module file 'types.mod'" when compiling a main.f90 program

A quick run down:
I'm new to fortran
I'm on a windows machine
Using sublime to edit an assignment fortran code
The assignment includes a main.f90 file (see the below image of the code for that file)
This main.f90 code calls in 3 different modules: 'types' and 'analytic_functions', and
'euler_formulas'
The following error keeps appearing whenever I try to run the command gfortran main.f90 in my windows command prompt:
Fatal Error: Can't open module file 'types.mod' for reading at (1): No such file or directory compilation terminated.
How do I fix this issue? All help will be greatly appreciated.
Here's the main.f90 code:
module read_write
use types
use analytic_functions, only : second_derivative_f
use euler_formulas, only : euler_3points
implicit none
private
public read_input, write_derivatives
contains
I don't know if this would help but here's the 'types.f90' code:
module types
! The iso_fortran_env is an intrinsic module that should already be
! inside of your compiler
use iso_fortran_env
implicit none
integer, parameter :: sp = REAL32 !< single precision kind
integer, parameter :: dp = REAL64 !< double precision kind
integer, parameter :: qp = REAL128!< quadruple precision kind
real(dp), parameter :: pi=acos(-1.0_dp)!< π = 3.141592...
end module types
Note: these .mod files are more or less like C headers, they allow the compiler to check types at compile time, which was usually not possible in Fortran 77 when compiling from several source files. They are created when you compile the modules.
Hence, you have first to compile the modules. Note that to compile and link main.f90, you also have to pass the object files to gfortran, otherwise the linker won't be able to resolve references to functions from these modules.
gfortran -c types.f90
gfortran -c analytic_functions.f90
gfortran -c euler_formulas.f90
gfortran main.f90 types.obj analytic_functions.obj euler_formulas.obj
The gfortran compiler is also able to compile all files at once, but you must pass the files in a specific order: if program or module B uses module A, then B.f90 must be after A.f90 on the command line. This is necessary for the compiler to find the .mod files when they are used.
gfortran types.f90 analytic_functions.f90 euler_formulas.f90 main.f90

Compile Module and Main Program In the Same File Using GFortran?

I am new to fortran and I have this fortran90 program I am trying to run where the module and the main are in the same file called main.f90:
module real_precision
implicit none
integer, parameter :: sp = selected_real_kind(1)
integer, parameter :: dp = selected_real_kind(15)
end module real_precision
program main_program
use real_precision
implicit none
real(sp) :: a = 1.0_sp
real(dp) :: b = 1.0_dp
print *, a
print *, b
end program main_program
And I compiled it once doing:
gfortran main.f90 -o main.x
Then run it:
./main.x
However I made a change to the module and saved it but compiling and running it this same way provides the same output which leads me to think that the module needs to be compiled? How do I compile both where they're in the same file? I could make the module a separate file but I'd like to know how to do it this way!
selected_real_kind(p) returns the kind parameter of a real with precision at least p digits (if one exists). It does not give a kind parameter for a real with exactly that precision.
If your compiler has does not have a real with precision less than q then selected _real_kind(q) and selected_real_kind(q-1) will not return different kind parameters.

External naming of fortran subroutine inside a module using GCC

My objectif is to rename a fortran subroutine inside a module to be easily callable by C code (i.e. without the __<modulename>_MOD_ prefix), and using GCC-6.3.0. I cannot use bind(c,name='') even if it works great. I have read that I should use interface, but without any success. Here is the MWE:
module testmodule
interface
subroutine func02
!GCC$ ATTRIBUTES CDECL :: func01
end subroutine
end interface
contains
subroutine func01
print*,"func01"
end subroutine
end module
I compile using command gfortran -c test.f90 and then I check if the subroutine is correctly renamed using nm test.o, but there is no sign of func02.
Any help appreciated.
You can use BIND(C) to rename the subroutine. Whatever you read about INTERFACE seems to be a red herring.
module testmodule
contains
subroutine func01() bind(c, name='func2')
print*,"func01"
end subroutine
end module
With the simple command 'gfortran -c a.f90', I see the following results
nm a.o
U _gfortran_st_write
U _gfortran_st_write_done
U _gfortran_transfer_character_write
00000000 T func2

How does using modules that use other modules affect compilation? (gfortran)

I asked a question about some strange behavior from a Fortran compiler here:
gfortran compiler cannot find misspelled full directory
Basically, the compiler sporadically** complains that a file is missing, but the problem is that the printed name of the file (full path, actually) is misspelled, so no wonder it's "missing". I thought that I resolved the problem by using relative paths, but it turns out that the problem was just dormant. Here's an example of one such complaint:
C:\Users\charl\Documents\GitHub\MOONS>gfortran -fopenmp -g -fimplicit-none -cpp
C:/Users/charl/Documents/GitHub/MOONS/code/globals/current_precision.f90
...
C:/Users/charl/Documents/GitHub/MOONS/code/solvers/induction/init_Bfield.f90
C:/Users/charl/Documents/GitHub
gfortran: error:
C:/Users/charl/Documents/GitHubMOONS/code/solvers/induction/init_Sigma.f90: No such file or directory
Notice that the forward slash ('/') is missing between GitHub and MOONS, and instead reads "GitHubMOONS". This path was correctly written in the makefile.
** I say sporadically because changing lines in the code sometimes results in the error disappearing. Similarly, removing some unused modules (that compile just fine) from my compilation list results in the error disappearing.
The compiler I'm using is:
GNU Fortran (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 4.9.2 Copyright (C) 2014 Free Software Foundation, Inc.
But I've seen the same problem with more recent compilers, e.g.:
x86_64-7.1.0-release-posix-seh-rt_v5-rev2
I think I am seeing a trend with when this error occurs, and it seems to occur more frequently when modules pass on public interfaces to other modules.
Question
So, my question is, given the following two modules:
module add_int_mod
implicit none
private
public :: add
interface add; module procedure add_int; end interface
contains
subroutine add_int(a,b)
implicit none
integer,intent(inout) :: a
integer,intent(in) :: b
a = a + b
end subroutine
end module
module add_all_mod
use add_int_mod
implicit none
private
public :: add
end module
What is the difference between these two programs, if any?
Program 1
program main
use add_all_mod ! only difference
implicit none
integer :: a,b
a = 0
b = 1
call add(a,b)
write(*,*) 'a = ',a
write(*,*) 'b = ',b
end program
Program 2
program main
use add_int_mod ! only difference
implicit none
integer :: a,b
a = 0
b = 1
call add(a,b)
write(*,*) 'a = ',a
write(*,*) 'b = ',b
end program
I appreciate any help/suggestions.

Change of directory in Fortran in a non compiler-specific way

I wish to change the working directory in a Fortran 90 code. Is it possible to do this in a non compiler-specific way? Here is my code:
program change_directory
integer :: ierr
call system("mkdir -p myfolder/")
!call system("cd myfolder/") !doesn't work
ierr = chdir("myfolder")
if (ierr.NE.0) then
write(*,'(A)') "warning: change of directory unsuccessful"
end if
open(unit=33,file="myfile.txt",iostat=ierr)
if (ierr.EQ.0) then
write(unit=33,fmt='(A)') "Test message"
close(unit=33)
end if
end program change_directory
Clearly, using cd myfolder/ in a system call doesn't work. The Intel reference says I need to add 'use ifport'. There's no such mention in the GCC reference, though. Leaving out 'use ifport', I can compile the above code under ifort without any trouble. When I put it in, however, it won't compile with gcc (because gcc doesn't have the ifport module)--and not only that, it won't compile under Intel Fortran either--I'm getting the following error:
$ ifort change_dir.f90 -o change_dir
change_dir.f90(5): error #6552: The CALL statement is invoking a function subprogram as a subroutine. [SYSTEM]
call system("mkdir -p myfolder/")
---------^
compilation aborted for change_dir.f90 (code 1)
So my question is the following: is there a better way to do this? I'd like to keep my code as compiler-independent as possible. At the moment, I primary use gfortran/ifort and mpif90/mpiifort.
See also Is there any way to change directory using C language? . You can make your own interface to the chdir() POSIX call to be independent of the Intel's interface. On Windows it is similar.
module chdir_mod
implicit none
interface
integer function c_chdir(path) bind(C,name="chdir")
use iso_c_binding
character(kind=c_char) :: path(*)
end function
end interface
contains
subroutine chdir(path, err)
use iso_c_binding
character(*) :: path
integer, optional, intent(out) :: err
integer :: loc_err
loc_err = c_chdir(path//c_null_char)
if (present(err)) err = loc_err
end subroutine
end module chdir_mod
program test
use chdir_mod
call chdir("/")
call system("ls -l")
end
and when run
> gfortran chdir.f90
> ./a.out
celkem 120
drwxr-xr-x 2 root root 4096 15. říj 14.42 bin
drwxr-xr-x 5 root root 4096 15. říj 14.43 boot
...
On ifort it works too as it does on sunf90.
(Note: this relies on default character being the same as c_char. That is quite a safe assumption. If it is not the case the compiler will complain and a conversion has to be made.)

Resources