I'm attempting to compile a subroutine sendmsg.f90 that we previously compiled with lf90 as 32 bit now with gcc as 64 bit. The purpose is to link it with other 64 bit subroutines compiled with gcc.
subroutine UpdateDisplay(WINHAND,NTPS,QCANCEL,NITER)
use win32mod
implicit none
integer WINHAND, NTPS, MESSNUM, NITER, QCANCEL
! SendMessageA is a Windows function
! WINHAND = handle of window (from ISDev code)
! MESSNUM = message number (assigned by ISDev)
! NTPS = number of year iteration currently on (WParam)
! DUM = 0 (LParam)
MESSNUM = 1114
QCANCEL = SendMessageA(carg(WINHAND),carg(MESSNUM),carg(NTPS), carg(NITER))
end subroutine
We have Lahey Fortran 7.5 which has the lf90 compiler and gcc (which uses gfortran) and something called lgf (which I suppose uses gcc, is that right?).
I'm new to Windows programming (and Fortran). Can code compiled with gcc call the Windows API? Should I use ISO_C_BINDING?
Should I even do this or should I try to link the .obj file created by lf90 with the .o files created by gcc?
Thanks for your help!
Update: I've tried calling the windows API with:
MODULE SND_C
interface
integer(C_LONG) FUNCTION SendMessage &
(WINHAND,MESSNUM,NTPS, NITER) &
bind(C,Name='SendMessage')
use ISO_C_BINDING
implicit NONE
integer(C_LONG), VALUE :: WINHAND
integer(C_LONG), VALUE :: MESSNUM
integer(C_LONG), VALUE :: NTPS
integer(C_LONG), VALUE :: NITER
end function SendMessage
end interface
END MODULE SND_C
subroutine UpdateDisplay(WINHAND,NTPS,QCANCEL,NITER)
USE ISO_C_BINDING, ONLY: C_LONG
USE SND_C
implicit none
integer(C_LONG) WINHAND, NTPS, MESSNUM, NITER, QCANCEL
! SendMessageA is a Windows function
! WINHAND = handle of window (from ISDev code)
! MESSNUM = message number (assigned by ISDev)
! NTPS = number of year iteration currently on (WParam)
! DUM = 0 (LParam)
!GCC$ ATTRIBUTES DLLEXPORT :: UpdateDisplay
MESSNUM = 1114
QCANCEL = SendMessage(WINHAND,MESSNUM,NTPS, NITER)
end subroutine
but when I try to compile with "gcc -m64 sendmsg.f90" I get the error:
C:\Users\StephanieJ\Documents\Lahey-Fujitsu Fortran>gcc -m64 sendmsg.f90
c:/progra~2/lahey-~1/v7.5/gcc-gf~1/bin/../lib/gcc/x86_64-w64-mingw32/4.7.4/../..
/../../x86_64-w64-mingw32/lib/../lib/crt2.o: In function `__tmainCRTStartup':
c:\gccbuild\mingw-crt\build32-64\mingw-w64-crt/../../mingwsvn/mingw-w64-crt/crt/
crtexe.c:323: undefined reference to `__laheypause'
C:\Users\STEPHA~2\AppData\Local\Temp\ccWjjo5b.o:sendmsg.f90:(.text+0x3e): undefi
ned reference to `SendMessage'
c:/progra~2/lahey-~1/v7.5/gcc-gf~1/bin/../lib/gcc/x86_64-w64-mingw32/4.7.4/../..
/../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o):
In function `main':
c:\gccbuild\mingw-crt\build32-64\mingw-w64-crt/../../mingwsvn/mingw-w64-crt/crt/
crt0_c.c:18: undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
Does this approach make sense? Why is my reference to SendMessage undefined?
Probably the easiest way to call the API is through a C wrapper function that might look like this:
The lower case and trailing underscore are to match the Fortran default function naming. If you suppose that the file name is updatedisplay.c, compile it with the command:
gcc -c updatedisplay.c
On the Fortran side, instead of sending zero as the window handle, use C_NULL_PTR from ISO_C_BINDING instead. You can then link the object file updatedisplay.o with the Fortran code that originally called the Fortran function of the same name, and it should work.
To get rid of the laheypause thing, link with the file lgfpstub.o from the proper lib directory either x86_64-w64-mingw32\lib for x86_64 or x86_64-w64-mingw32\lib32 for x86.
Hope this helps!