2013-08-28 5 views
1

이전에 lf90으로 컴파일 한 서브 루틴 sendmsg.f90을 gcc가 64 비트 인 32 비트로 컴파일하려고합니다. 그 목적은 gcc로 컴파일 된 다른 64 비트 서브 루틴과 링크하는 것입니다. gcc (gfortran)로 컴파일 할 때 windows API 함수 (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 

우리는 lf90 컴파일러와 GCC (gfortran을 사용하는) 무엇인가라는 LGF 가지고있는 Lahey 포트란 7.5이 (내가 GCC를 사용한다고 가정 권리이다?)를.

저는 Windows 프로그래밍 (및 포트란)을 처음 사용합니다. gcc로 컴파일 된 코드는 Windows API를 호출 할 수 있습니까? ISO_C_BINDING을 사용해야합니까?

gcc에서 만든 .o 파일과 lf90으로 만든 .obj 파일을 연결해야합니까?

도움 주셔서 감사합니다.

업데이트 : 내가 가진 윈도우 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에 대한 참조가 정의되지 않은 이유는 무엇입니까?

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

낮은 경우와 후행는 포트란 기본 기능 이름과 일치하도록되어 밑줄 : API를 호출하는

+1

Fortran에서 Windows 64 비트 API를 호출 할 수 있지만 API가 변경되었음을 인식해야하며 [ABI] (https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention)도 알고 있어야합니다. 특정 인터페이스 (windows.h와 같은 의미)가 필요합니다. –

+2

64 비트에서 STDCALL에 대해 걱정할 필요가 없으므로 실제로 API 루틴을 호출하는 것이 더 쉽습니다. 필요한 것은 적절한 인터페이스이며, BIND (C)를 사용하여 대소 문자를 혼합 한 이름을 지정할 수 있습니다. ISO_C_BINDING을 (를) 사용하면 종류 값에 도움이되지만 그다지 도움이되지 않을 수 있습니다. 인텔 포트란은 수천 가지 Windows API 루틴에 대한 선언을 제공합니다. 다른 Windows 컴파일러에서도 마찬가지입니다. –

+1

아마 SendMessageA 여야합니까? Windows API에서 일반적으로 문자를 다루는 함수는 A (ANSI charset)로 끝나는 버전과 W (와이드, 즉 유니 코드)로 끝나는 버전 두 가지가 있습니다. C 언어에서는 다른 언어를 호출 할 때가 아니라 자동으로 이름이 선택됩니다 (아마도 windows.h의 macris로). –

답변

2

아마 가장 쉬운 방법은 다음과 같을 수는 C 래퍼 기능을 통해입니다. 에서 C_NULL_PTR를 사용하는 대신 창 핸들로 제로를 보내는,

의 gcc -c updatedisplay.c

포트란 측면에서 : 파일 이름이 updatedisplay.c이 있다고 가정하면 는 명령으로 컴파일 대신 ISO_C_BINDING 그런 다음 updatedisplay.o라는 오브젝트 파일을 원래 같은 이름의 Fortran 함수라고 불렀던 Fortran 코드와 연결할 수 있습니다. 그러면 작동합니다.

laheypause 문제를 제거하려면 x86_64의 경우 x86_64-w64-mingw32 \ lib 또는 x86_64-w64-mingw32 \ lib32 (x86의 경우) 중 적절한 lib 디렉토리에서 lgfpstub.o 파일로 연결하십시오.

희망이 도움이됩니다.

+1

위의 코드는 정확하게 작동합니다. Fortran에서 컴파일 한 .o 파일을 c에서 컴파일 한 .o 파일과 연결할 수 있다는 것을 알지 못했습니다. –