0

Windowsで実行可能なfortranからfortran dllの関数を呼び出す方法を学ぼうとしています。私は日食でgfortran 4.7とphotranを使用しています。

私のテスト dll には、hello.f90 に 1 つの関数があります。

こんにちは.f90

subroutine hello
    implicit none
    print *, "Hello World!"
end subroutine hello

次のメイクファイルを使用します。

all:
    gfortran -Wall -c hello.f90
    gfortran -shared -o hello.dll hello.o

Dependency Walker は、関数「hello_」がエクスポートされていることを確認します。

今、動的に呼び出すプログラムを構築しようとしています。オンラインで見つけた例に基づいて次のものを作成しましたが、コンパイルされません。

main.f90

program main
    implicit none
    integer :: p
    pointer (q, hello)
    p = loadlibrary("hello.dll")
    q = getprocaddress(p, "hello_")
    call hello
end program main

メイクファイル

all:
    gfortran -Wall -pedantic -fcray-pointer main.f90 

エラー メッセージは、関数 LoadLibrary (および getprocaddress) に IMPLICIT 型がないことです。これは、これらの関数が定義されておらず、何らかの方法でヘッダーを含める必要があることを意味していると思われます。そうですか?c:\mingw\include\winbase.h で loadlibrary の宣言を見つけました

乾杯、

マルク

4

1 に答える 1

7

LoadLibraryとGetProcAddressはWindowsAPIルーチンです。他の非組み込み関数と同様に、これらの関数のタイプを宣言する必要があります。また、これらのAPIの性質を考えると、さらに進んで完全なインターフェースを提供する必要があります。

32ビットWindows用にコンパイルしている場合、それらのAPIはstdcall呼び出し規約を使用します。これを指定するには、gfortranソースディレクティブ拡張機能を使用する必要があります。

(64ビットのWindowsでは、stdcallはCの呼び出し規約と同じように定義されています。ソースディレクティブは効果がありません。)

規約制御を呼び出すために、DLLコードを次のように変更した場合:

SUBROUTINE hello() BIND(C, NAME='hello')
  IMPLICIT NONE
  PRINT *, 'Hello'
END SUBROUTINE hello

次に、次のメインプログラムが結果のDLLをロードし、そのプロシージャを実行します。

PROGRAM Main
  USE, INTRINSIC :: ISO_C_BINDING, ONLY:  &
      C_F_PROCPOINTER, C_FUNPTR, C_INTPTR_T,  &
      C_NULL_CHAR, C_CHAR, C_ASSOCIATED

  IMPLICIT NONE

  INTERFACE 
     FUNCTION LoadLibrary(lpFileName) BIND(C,NAME='LoadLibraryA')
        USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INTPTR_T, C_CHAR
        IMPLICIT NONE 
        CHARACTER(KIND=C_CHAR) :: lpFileName(*) 
        !GCC$ ATTRIBUTES STDCALL :: LoadLibrary 
        INTEGER(C_INTPTR_T) :: LoadLibrary 
     END FUNCTION LoadLibrary 

     FUNCTION GetProcAddress(hModule, lpProcName)  &
         BIND(C, NAME='GetProcAddress')
       USE, INTRINSIC :: ISO_C_BINDING, ONLY:  &
           C_FUNPTR, C_INTPTR_T, C_CHAR
       IMPLICIT NONE
       !GCC$ ATTRIBUTES STDCALL :: GetProcAddress
       TYPE(C_FUNPTR) :: GetProcAddress
       INTEGER(C_INTPTR_T), VALUE :: hModule
       CHARACTER(KIND=C_CHAR) :: lpProcName(*)
     END FUNCTION GetProcAddress      
  END INTERFACE

  ABSTRACT INTERFACE
    SUBROUTINE hello_intf() BIND(C)
      IMPLICIT NONE
    END SUBROUTINE hello_intf
  END INTERFACE

  INTEGER(C_INTPTR_T) :: module_handle
  TYPE(C_FUNPTR) :: proc_address
  PROCEDURE(hello_intf), BIND(C), POINTER :: my_proc

  !****      

  module_handle = LoadLibrary(C_CHAR_'hello.dll' // C_NULL_CHAR)
  IF (module_handle == 0) STOP 'Unable to load DLL'

  proc_address = GetProcAddress( module_handle,  &
      C_CHAR_'hello' // C_NULL_CHAR )
  IF (.NOT. C_ASSOCIATED(proc_address))  &
      STOP 'Unable to obtain procedure address'

  CALL C_F_PROCPOINTER(proc_address, my_proc)

  CALL my_proc

END PROGRAM Main
于 2013-01-05T06:55:50.693 に答える