用gcc(gfortran)编译时可以调用windows api函数(64位)吗?

时间:2013-08-28 22:41:55

标签: winapi gcc fortran gfortran fortran-iso-c-binding

我正在尝试编译一个子程序sendmsg.f90,我们之前用lf90编译为32位,现在gcc为64位。目的是将它与用gcc编译的其他64位子程序链接。

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

我们有Lahey Fortran 7.5,它有lf90编译器和gcc(使用gfortran)和一些叫做lgf的东西(我想它使用gcc,是吗?)。

我是Windows编程(和Fortran)的新手。用gcc编译的代码可以调用Windows API吗?我应该使用ISO_C_BINDING吗?

我是否应该这样做,还是应该尝试将lf90创建的.obj文件与gcc创建的.o文件相关联?

感谢您的帮助!

更新: 我试过用以下方法调用windows API:

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

但是当我尝试使用“gcc -m64 sendmsg.f90”编译时,我收到错误:

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

这种方法有意义吗?为什么我对SendMessage的引用未定义?

1 个答案:

答案 0 :(得分:2)

调用API的最简单方法可能是通过一个可能如下所示的C包装函数:

#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);
}

小写和尾随下划线与Fortran默认函数命名相匹配。 如果您认为文件名是updatedisplay.c,请使用以下命令编译它:

gcc -c updatedisplay.c

在Fortran端,不使用零作为窗口句柄,而是使用ISO_C_BINDING中的C_NULL_PTR。 然后,您可以将目标文件updatedisplay.o链接到最初调用同名Fortran函数的Fortran代码,它应该可以工作。

要删除laheypause,请从正确的lib目录链接文件lgfpstub.o x86_64-w64-mingw32 \ lib for x86_64或x86_64-w64-mingw32 \ lib32 for x86。

希望这有帮助!