Frage

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?

War es hilfreich?

Lösung

Probably the easiest way to call the API is through a C wrapper function that might look like this:

#include <windows.h>
void updatedisplay_(  HWND *winhand, WPARAM  *ntps, LRESULT *qcancel, LPARAM *niter)
{
  //  integer NTPS, MESSNUM, NITER, QCANCEL
  /*
  !                  WINHAND = handle of window (from ISDev code)
  !                  MESSNUM = message number (assigned by ISDev)
  !                  NTPS = number of year iteration currently on (WParam)
  !                  DUM = 0 (LParam)  
  */
  UINT messnum = 1114;
  *qcancel = SendMessage(*winhand,messnum,*ntps,*niter);
}

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!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top