(문제의 내 확장 된 인터넷 검색 가까이 솔루션에 저를하지 않았다).
! dll1.f90
! gfortran dll1.f90 -shared -odll1.dll -Wl,--out-implib,libdll1.a
module not_used
use ISO_C_BINDING
implicit none
contains
function F(x) bind(C,name='F')
!GCC$ ATTRIBUTES DLLEXPORT :: F
real(C_DOUBLE) F
real(C_DOUBLE), intent(in) ::x
F = x**2
end function F
end module not_used
dll1.dll을 빌드하는 데 사용되는 명령 줄은 주석에 표시됩니다.
이제 우리는 포트란 주요 있습니다 위
! main1.f90
! fails:
! gfortran main1.f90 dll1.dll -omain1
! gfortran main1.f90 -L. -ldll1 -omain1
! works:
! gfortran main1.f90 dll1.dll -L. -ldll2 -omain1
! gfortran main1.f90 -L. -ldll1 -ldll2 -omain1
module mod1
implicit none
interface
function F(x)
import
implicit none
!GCC$ ATTRIBUTES DLLIMPORT :: F
double precision F
double precision, intent(in) :: x
end function F
end interface
end module mod1
program main1
use mod1
implicit none
double precision x, y
x = 13
y = f(x)
write(*,*) y
end program main1
처음 두 gfortran 명령 main1.exe를 구축하지 못한다. 두 번째 작업은 libdll2.a 파일이 필요하지만 dlltool.exe를 사용하여 만들 수 있습니다. dll2.def로 시작합니다.
; dlltool -z dll2.def --export-all-symbol dll1.dll
; dlltool -d dll2.def -l libdll2.a
LIBRARY dll1.dll
EXPORTS
f = F
위의 첫 번째 주석 행은 dll2.ool.exe에서 dll2.def의 시작점을 만드는 방법을 보여줍니다. 우리의 경우 출력물은 그다지 유용하지 않으므로 대부분 텍스트 편집기를 사용하여 시작점을 수정했습니다. dll2.def 파일은 dll1.dll과 링크하기 위해 usefule 인 libdll2.a 파일을 작성하므로 위의 LIBRARY 행을 사용하십시오. 내 보낸 심볼은 'F'였지만, gfortran은 'f'를 찾으므로 내보내기 섹션에서 이름을 바꿉니다.
그런 다음 위의 두 번째 주석 행을 통해 dlltool.exe를 사용하여 libdll2.a를 만듭니다. libdll2.a를 사용하면 6 또는 7 행의 주석에 따라 main1.f90을 컴파일 할 수 있습니다.
두 번째 방법은 함수에 바인딩 이름을 사용합니다. 이것은 함수가 상호 운용 될 것을 요구하지만, 그렇지 않다면 아마 gfortran에 의해 컴파일되지 않았다고 가정하면 어떤 간단한 방법으로도 호출 할 수 없을 것입니다. 여기에서 우리는 main2.f90에, 함수의 단지 다른 선언을 추가 dll2.lib 필요하지 않습니다 :
! main2.f90
! gfortran main2.f90 dll1.dll -omain2
! gfortran main2.f90 -L. -ldll1 -omain2
module mod2
use ISO_C_BINDING
implicit none
interface
function F(x) bind(C,name='F')
import
implicit none
!GCC$ ATTRIBUTES DLLIMPORT :: F
real(C_DOUBLE) F
real(C_DOUBLE), intent(in) :: x
end function F
end interface
end module mod2
program main2
use mod2
implicit none
double precision x, y
x = 13
y = f(x)
write(*,*) y
end program main2
이 코멘트에 주어진 gfortran 명령 중 하나를 사용하여 컴파일합니다.
마지막으로 당신은 main3.f90 같이 동적 링크를 사용할 수 있습니다 다음 gfortran 명령
! main3.f90
! gfortran main3.f90 dll1.dll -omain3
! gfortran main3.f90 -L. -ldll1 -omain3
module mod3
use ISO_C_BINDING
use ISO_C_BINDING, HANDLE => C_INTPTR_T
use ISO_C_BINDING, C_INTPTR_T => C_INTPTR_T
implicit none
abstract interface
function F(x) bind(C)
import
implicit none
real(C_DOUBLE) F
real(C_DOUBLE), intent(in) :: x
end function F
end interface
interface
function LoadLibrary(lpFileName) bind(C,name='LoadLibraryA')
import
implicit none
!GCC$ ATTRIBUTES STDCALL :: LoadLibrary
integer(HANDLE) :: LoadLibrary
character(kind=C_CHAR) lpFIleName(*)
end function LoadLibrary
function GetProcAddress(hModule,lpProcName) bind(C,name='GetProcAddress')
import
implicit none
!GCC$ ATTRIBUTES STDCALL :: GetProcAddress
type(C_FUNPTR) GetProcAddress
integer(HANDLE), value :: hModule
character(kind=C_CHAR) lpProcName(*)
end function GetProcAddress
end interface
end module mod3
program main3
use mod3, F1 => F
implicit none
double precision x, y
type(C_FUNPTR) ptr
procedure(F1), pointer :: F
integer(HANDLE) hModule
hModule = LoadLibrary('dll1.dll'//C_NULL_CHAR)
ptr = GetProcAddress(hModule,'F'//C_NULL_CHAR)
call C_F_PROCPOINTER(ptr,F)
x = 13
y = f(x)
write(*,*) y
end program main3
하나를 코멘트에 성공적으로 main3.exe을 구축합니다.
참고 : 재시험 중, main2.f90 및 main3.f90 메서드는 작동했지만 어떤 이유로 main1.f90 및 dll2.def를 사용하는 메서드가 더 이상 작동하지 않고 dll1.dll이 아닌 main1.exe에서 심볼 'f'를 찾으려고하기 때문에 런타임에 오류가 발생합니다. 이 시점에서 이유를 알 수 없습니다.
편집 : 글쎄, 위에서 만든 dll1.dll하고 그대로 main1.f90와 첫 번째 방법 일을 할 수있는 방법을 찾았지만, 그래서 나는 기다릴 것이다 like에게 정말하지 않습니다 다른 사람이 좀 더 맛있는 해결책을 제시하는지 확인하는 데는 며칠이 걸립니다. 그 시간이 지나도 이런 일이 일어나지 않고 누군가가 여전히 관심이 있다면 그는 나에게 생각 나게해야하고 내가 생각한 것을 올릴지도 모른다.
"별칭"을 사용하면! DEC $ ATTRIBUTES DLLIMPORT, DECORATE, ALIAS와 같은 다른 컴파일러와 비슷한 구성을 사용하고 있습니까? 'DISCON':: DISCON gfortran (확실하지 않음) 및 적어도이 대문자로이 동작을 변경하는 플래그를 찾을 수 없습니다. – PiWi