Intel Fortran Corrupts DLL - dll

I am building a dll with Intel Fortran via VS 2015. The output is a dll file with one subroutine (which I am sure is exported because I checked dll with depends tool). But when I try to use in in C priject, VC++ says that it cant read dll and file is corrupted (error LINK1107).
The fortran-side code is
subroutine ADD(x,y,z)
!DEC$ ATTRIBUTES DLLEXPORT, DECORATE, ALIAS : 'ADD' :: ADD
!DEC$ ATTRIBUTES REFERENCE :: x
!DEC$ ATTRIBUTES REFERENCE :: y
!DEC$ ATTRIBUTES REFERENCE :: z
integer x, y, z
z = x + y
end subroutine

Don't use the .dll file in the C project - instead use the import library (.lib) that was generated when the dll was built.

Related

how to call dll in fortran

I have one dll file which contains a function "ProcessWeather" and want to call this function in a fortran code, as shown below:
PROGRAM myprog
!DEC$ ATTRIBUTES DLLIMPORT :: EPLUSWTH
INTERFACE
SUBROUTINE ProcessWeather(InType,OutType,InFileName,OutFileName,ErrFlag)
CHARACTER(len=*), INTENT(IN) :: InType ! InputFile Type
CHARACTER(len=*), INTENT(IN) :: OutType ! OutputFile Type
CHARACTER(len=*), INTENT(IN) :: InFileName ! InputFile Name (Full path)
CHARACTER(len=*), INTENT(IN) :: OutFileName ! OutputFileName (Full path)
REAL(4), INTENT(OUT) :: ErrFlag ! If errors are found,
! set to true and put
! description put in file.
END SUBROUTINE
END INTERFACE
END PROGRAM
The dll file is put to the same place where I put the fortran file to.
When I compile the fortran code, I got the following error:
undefined reference to processweather_
Any suggestion will be highly appreciated.
If you are compiling with gfortran (as your comment seem to suggest) the !$DEC directives will be ignored. But you could use the GCC directives, namely the ATTRIBUTES directive and declare the attribute DLLIMPORT in it.
You could also just use the standard bind(C, name="the_name"). Also, as far as I remember, GCC did not require any attributes to make symbols externally visible when creating a DLL.

Case sensitiveness issue when calling an external DLL in Fortran and compiling with gfortran

I'm trying to call a DLL from a Fortran code compiled with gfortran. I'm importing DISCON_32.dll with:
!GCC$ ATTRIBUTES DLLIMPORT :: DISCON
and compiling with:
mingw32-gfortran "DISCON_32.dll" -cpp -ffree-line-length-none -fno-automatic -Wall -fdefault-real-8 -fno-underscoring -static BladedDLLInterface.o -o "my_program"
I get the error:
BladedDLLInterface.o:BladedDLLInterface.f90(.text+0x6cd): undefined reference to 'discon'
Note that entry point "discon" is here called as lowercase. When looking into the DLL with Dependency Walker, entry point is "DISCON" (uppercase).
I cannot change the case of the DLL. Is there a way to tell my Fortran code to look for "DISCON" entry point instead of "discon"?
(My extended googling of the question did not get me closer to a solution)
There are 3 ways to do this: let's make an example DLL and Fortran main to demonstrate the problem.
! dll1.f90
! gfortran dll1.f90 -shared -odll1.dll -Wl,--out-implib,libdll1.a
module not_used
use ISO_C_BINDING
implicit none
contains
function F(x) bind(C,name='F')
!GCC$ ATTRIBUTES DLLEXPORT :: F
real(C_DOUBLE) F
real(C_DOUBLE), intent(in) ::x
F = x**2
end function F
end module not_used
The command line use to build dll1.dll is shown in the comments.
Now we have a Fortran main:
! main1.f90
! fails:
! gfortran main1.f90 dll1.dll -omain1
! gfortran main1.f90 -L. -ldll1 -omain1
! works:
! gfortran main1.f90 dll1.dll -L. -ldll2 -omain1
! gfortran main1.f90 -L. -ldll1 -ldll2 -omain1
module mod1
implicit none
interface
function F(x)
import
implicit none
!GCC$ ATTRIBUTES DLLIMPORT :: F
double precision F
double precision, intent(in) :: x
end function F
end interface
end module mod1
program main1
use mod1
implicit none
double precision x, y
x = 13
y = f(x)
write(*,*) y
end program main1
The first two gfortran commands shown above fail to build main1.exe. The second two work, but we need a libdll2.a file, and we can create it with dlltool.exe. We start with dll2.def
; dlltool -z dll2.def --export-all-symbol dll1.dll
; dlltool -d dll2.def -l libdll2.a
LIBRARY dll1.dll
EXPORTS
f = F
The first comment line above shows how to dlltool.exe to create a starting point for dll2.def. The output is not very useful in our case, so mostly we used a text editor to modify the starting point. The dll2.def file will create a libdll2.a file that is usefule for linking with dll1.dll, thus the LIBRARY line above. The symbol that got exported was 'F', but gfortran is going to look for 'f', so we rename it in the exports section.
Then we use dlltool.exe to create libdll2.a via the second comment line above. Having a libdll2.a means we can compile main1.f90 according to the comments in lines 6 or 7.
The second method uses a binding name for the function. This requires the function to be interoperable, but if it isn't then you probably couldn't invoke it in any simple way given that it probably wasn't compiled by gfortran. Here we don't need an extra dll2.lib, just a different declaration of the function in main2.f90:
! main2.f90
! gfortran main2.f90 dll1.dll -omain2
! gfortran main2.f90 -L. -ldll1 -omain2
module mod2
use ISO_C_BINDING
implicit none
interface
function F(x) bind(C,name='F')
import
implicit none
!GCC$ ATTRIBUTES DLLIMPORT :: F
real(C_DOUBLE) F
real(C_DOUBLE), intent(in) :: x
end function F
end interface
end module mod2
program main2
use mod2
implicit none
double precision x, y
x = 13
y = f(x)
write(*,*) y
end program main2
This compiles with either of the gfortran commands given in the comments.
Finally you could use dynamic linking as in main3.f90:
! main3.f90
! gfortran main3.f90 dll1.dll -omain3
! gfortran main3.f90 -L. -ldll1 -omain3
module mod3
use ISO_C_BINDING
use ISO_C_BINDING, HANDLE => C_INTPTR_T
use ISO_C_BINDING, C_INTPTR_T => C_INTPTR_T
implicit none
abstract interface
function F(x) bind(C)
import
implicit none
real(C_DOUBLE) F
real(C_DOUBLE), intent(in) :: x
end function F
end interface
interface
function LoadLibrary(lpFileName) bind(C,name='LoadLibraryA')
import
implicit none
!GCC$ ATTRIBUTES STDCALL :: LoadLibrary
integer(HANDLE) :: LoadLibrary
character(kind=C_CHAR) lpFIleName(*)
end function LoadLibrary
function GetProcAddress(hModule,lpProcName) bind(C,name='GetProcAddress')
import
implicit none
!GCC$ ATTRIBUTES STDCALL :: GetProcAddress
type(C_FUNPTR) GetProcAddress
integer(HANDLE), value :: hModule
character(kind=C_CHAR) lpProcName(*)
end function GetProcAddress
end interface
end module mod3
program main3
use mod3, F1 => F
implicit none
double precision x, y
type(C_FUNPTR) ptr
procedure(F1), pointer :: F
integer(HANDLE) hModule
hModule = LoadLibrary('dll1.dll'//C_NULL_CHAR)
ptr = GetProcAddress(hModule,'F'//C_NULL_CHAR)
call C_F_PROCPOINTER(ptr,F)
x = 13
y = f(x)
write(*,*) y
end program main3
Either of the gfortran commands in the comments successfully builds main3.exe.
Note: on retesting, the main2.f90 and main3.f90 methods worked, but for some reason the method with main1.f90 and dll2.def no longer works, failing at runtime because it's trying to find the symbol 'f' in main1.exe rather than dll1.dll. Can't figure out why at this point.
EDIT: Well, I found a way to make the first approach work with the dll1.dll created above and the main1.f90 as it is, but I don't really like it so I'll wait a few days to see if someone else comes up with a more palatable solution. If, after that time, this hasn't happened and someone is still interested, he should remind me and I may post what I came up with.

Fortran .mod file doesn't update when compiling [duplicate]

I am working with GFortran and CodeBlocks but I'm having an issue about Modules and Multiple files.
i keep getting this error:
Fatal Error: Can't open module file 'mesh.mod' for reading at (1): No such file or directory
For some reason, GFortran is not building the 'mesh.mod' file.
This problem does not occur when I put all the code in a single .f90 file.
Bellow is an example of code that this error happens.
main.f90
MODULE MESH
IMPLICIT NONE
INTEGER :: IMAX,JMAX,NMAX
REAL(8), ALLOCATABLE :: XD(:),YD(:),FX(:,:),FY(:,:)
REAL(8) :: PI,E,DX,DY,H,L,RHO,MU
PARAMETER (PI = ACOS(-1.D0))
PARAMETER (E = 2.718)
END MODULE MESH
!**************************************************************
program Cavity
Use Mesh
implicit none
Real(8), Allocatable :: func(:)
Real(8) :: Der,DfDx
integer :: i
IMAX=10
DX=1./10
Allocate(xd(IMAX),func(IMAX))
Do i=1,IMAX
xd(i)=i*DX
End Do
Do i=1,IMAX
func(i) = xd(i)**2
End Do
Der=Dfdx(func,2)
Write(*,*) Der
End program Cavity
Derivatives.f90
Real(8) Function DfDx(f,i)
Use Mesh
implicit none
Real(8) :: f(1:Imax)
integer :: i
DfDx=(f(i+1)-f(i-1))/(2d0*dx)
return
end function DfDx
When I use console command line compilation instead of CodeBlocks interface I already solved this problem (Compiling Multiple Files with modules) but I'm still getting this problem with CodeBlocks.
Does anyone know how to solve this issue?
Assuming what you have written is how your code is, then it appears that the problem is that the module mesh is inside the main program and not a separate file. You should have three files: Mesh.f90, Derivatives.f90 and Main.f90.
Mesh.f90 is exactly as you have it,
module Mesh
implicit none
integer :: IMAX,JMAX,NMAX
real(8), allocatable :: XD(:),YD(:),FX(:,:),FY(:,:)
real(8) :: PI,E,DX,DY,H,L,RHO,MU
parameter (PI = ACOS(-1.D0))
parameter (E = 2.718)
end module Mesh
Derivatives.f90 should be written as another module, using contains:
module Derivatives
use mesh
contains
real(8) function dfdx(f,i)
real(8) :: f(i:imax)
integer :: i
DfDx=(f(i+1)-f(i-1))/(2d0*dx)
end function dfdx
end module Derivatives
and the Main.f90 will then use both modules. Note that I had to eliminate the variable DfDx; this is because it conflicts with the function DfDx in module Derivatives
program Cavity
Use Mesh
use Derivatives
implicit none
Real(8), Allocatable :: func(:)
Real(8) :: Der
integer :: i
IMAX=10
DX=1./10
Allocate(xd(IMAX),func(IMAX))
Do i=1,IMAX
xd(i)=i*DX
End Do
Do i=1,IMAX
func(i) = xd(i)**2
End Do
Der=Dfdx(func,2)
Write(*,*) Der
End program Cavity
I do not know how CodeBlocks works, but I would presume it lets you choose the compilation order. If that is the case, you should compile Mesh.f90 first, then Derivatives.f90, then compile Main.f90 before linking them to an executable.
When I compiled & linked them, I got an answer of 0.200000002980232; hopefully that links up to what you have as well.
On codeblock, you may go to Project properties > Build targets
Then select the file you want to build first (say mod.f90).
In the "Selected file properties" go to "Build"
Here,change the priority weight. Lower weight implies the file will be built first.
The problem is that in CodeBlocks "projects are built in the order of appearence, from top to bottom" (CodeBlocks Wiki), in other words, the files are compiled alphabetically.
Which means that in my case, Derivatives.f90 was being compiled before than Main.f90 causing the error.
A way to circumvent the problem is to set only the Main.f90 file as build target in CodeBlocks:
Menu Project/Properties...
In Build Target Files at the tab Build targets check only Main.f90
And use the command Include 'File_Name.f90' inside the Main.f90 code to include the other f90 files for compilation in the right order.

object oriented features with Solaris/Oracle Fortran compiler

I have been trying to compile an O-O fortran code with the fortran compiler of the Oracle Solaris Studio 12.4 suite (the latest as far as I know). But the compiler crashes. Here is a simplified version of my problem.
I define two simple types with one type-bound procedure each. One of the procedures has a variable of the other type as dummy argument:
MODULE MY_MODULE
type type0
real :: value = 0
contains
procedure :: print_value
end type type0
type type1
real :: value = 0
contains
procedure :: print_diff
end type type1
CONTAINS
subroutine print_value(self)
class(type0), intent(in) :: self
print*, self%value
end subroutine print_value
subroutine print_diff(self,var0)
class(type1), intent(in) :: self
type(type0), intent(in) :: var0
print*,self%value - var0%value
end subroutine print_diff
END MODULE MY_MODULE
PROGRAM MY_PROG
use my_module, only: type0,type1
type(type0) :: var0
type(type1) :: var1
var0%value = 3
var1%value = 10
call var1%print_diff(var0)
END PROGRAM MY_PROG
This program compiles and executes fine with gfortran:
[> gfortran myprog.f03 -o myprog.x
[> ./myprog.x
7.0
However, compilation with the Solaris f95 crashes:
[> f95 myprog.f03 -o myprog.x
f90: Internal Error, code=fw-interface-ctyp1-796, last src=myprog.f03:4
If I do any further simplification to the source code, then f95 compiles successfully. For instance, it works fine if:
type0 has no type-bound procedure
type1 has no type-bound procedure
procedure print_diff is replaced by a subroutine with no other argument than self
Is there anything I am doing wrong?
Is there an installation problem with my Solaris compiler? Is someone able to compile this code successfully with an other Solaris compiler?
Does someone know what the error code means (I haven't been able to find that out)?
After reporting my problem to Oracle, I just got their answer:
Thank you for reporting this and sorry for the problem. This is a known problem. It has already been fixed in our current development and ported to Studio 12.4. If you have a support contract, you can get the Studio 12.4 patch for it, otherwise the next release will contain the fix.

Cannot create .lib file for a 64 bit Fortran DLL

I have written some wrapper functions in c++ for some old Fortran (g77, I think) code. I created the .dll and .lib using an old Visual Fortran compiler, and have everything linked up and working in visual studio.
The problem I have now is creating an equivalent 64 bit version. I have installed gfortran and created a 64 bit .dll but no .lib was generated along with it, and I can't seem to link to the DLL or call any of the fortran functions without it.
I created my 64 bit .dll with the commands...
$ gfortran -c {filenames.for}
$ gfortran -m64 -shared -mrtd -o dll_foo.dll {filenames.o}
And here is a sample subroutine from the fortran...
SUBROUTINE KFACT(TR, RHOL, RHOV, FLIQ, FVAP, XK, IWANT, PROPR)
!DEC$ ATTRIBUTES DLLEXPORT :: KFACT
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
INCLUDE 'nprop.cmn'
DIMENSION PROPR(NPROP)
DIMENSION IWANT(NPROP)
C
C SET IWANT VECTOR TO RETURN FUGACITY COEFFICIENT
C
CALL IVZERO(IWANT, NPROP)
IWANT(13) = 1
C
C CALL PROP2 TO RETURN VAP AND LIQ FUGACITY COEFFICIENTS
C
CALL PROPS2(IWANT, 0, TR, RHOL, PROPR)
FLIQ = PROPR(13)
CALL PROPS2(IWANT, 0, TR, RHOV, PROPR)
FVAP = PROPR(13)
C
XK = FLIQ / FVAP
C
RETURN
END
C
SUBROUTINE PDP(DEL, TR, PR, DPRDD, IWANT, PROPR)
How can I create a .dll and .lib file to be linked to, from my Visual Studio (2005) c++ project?
/////////////////////////////UPDATE/////////////////////////////
I have been able to create a .lib file by using the following commands...
ar -cru libName.lib {filenames.o}
ranlib libName.lib
After adding this lib to my Additional Dependencies in VS, I get LNK errors for all of the fortran functions when they are called. The fortran declarations in the c++ look like...
extern "C" void PSAT(double& TK, double& PMPA, double& RHOL, double& RHOV, int IWORK[], double PROPR[], int& IERR);
and the LNK errors for this function...
error LNK2028: unresolved token (0A00004A) "extern "C" void __cdecl PSAT(double &,double &,double &,double &,int * const,double * const,int &)" (?PSAT##$$J0YAXAEAN000QEAHQEANAEAH#Z) referenced in function "double __cdecl PFTH(double,double,int)" (?PFTH##$$FYANNNH#Z)
error LNK2019: unresolved external symbol "extern "C" void __cdecl PSAT(double &,double &,double &,double &,int * const,double * const,int &)" (?PSAT##$$J0YAXAEAN000QEAHQEANAEAH#Z) referenced in function "double __cdecl PFTH(double,double,int)" (?PFTH##$$FYANNNH#Z)
I have tried adding different directives in the fortran code to resolve the names like but I have been unsuccessful.
I don't know if the problem lies in the c code, the fortran code, or the creation of the .lib file.
Any help would be greatly appreciated!
Unlike MS based linkers, GNU based linkers do not need a .lib file. All you need to do is prefix the dll with lib. In your case, it would be libdll_foo.dll. To link, just drop the lib. For instance, to link to a program called main
gfortran -o main.exe -ldll_foo main.f95
It needs libdll_foo to be on the path. Alternatively, you could tell it where to find libdll_foo.dll with the -L parameter.
I ended going with CMake to create my X64 .lib file. Here is the CMakeLists if anyone is interested.
cmake_minimum_required(VERSION 2.8)
enable_language(Fortran)
set(CMAKE_Fortran_CREATE_SHARED_LIBRARY ON)
set(CMAKE_Fortran_COMPILER gfortran)
add_library(Steam64 SHARED AUXPK.o eospk.o INTPK.o PROPPK.o SOLVPK.o coef.cmn coefig.cmn nprop.cmn wconst.cmn)
SET_TARGET_PROPERTIES(Steam64 PROPERTIES LINKER_LANGUAGE C ARCHIVE_OUTPUT_DIRECTORY "C:/Users/MYNAH/Desktop/fortranSource/build")
add_executable(testf AUXPK.o eospk.o INTPK.o PROPPK.o SOLVPK.o coef.cmn coefig.cmn nprop.cmn wconst.cmn)
target_link_libraries(testf Steam64)