[Julia] Fortran Dll 불러오기

포트란에서 자주 사용되는 기능들은 함수나 루틴에 저장되어서 자주 사용되곤 합니다. 여러가지 데이터 타입이 입력값으로 들어가는데 오늘은 여러가지 형태의 입력값을 다루겠습니다. 먼저 첫번째로 정수 타입을 살펴보면 다음과 같습니다.

1. 포트란 라이브러리 코드 : test.f90
SUBROUTINE ADDROUTINE(M,N,K)
!DEC$ ATTRIBUTES DLLEXPORT :: ADDROUTINE
K = M + N
END SUBROUTINE

SUBROUTINE MULTROUTINE(X,Y,Z)
!DEC$ ATTRIBUTES DLLEXPORT :: MULTROUTINE
REAL(8) :: X(2), Y(2), Z(2)
DO I=1,2
Z(I) = X(I) * Y(I)
END DO
END SUBROUTINE

SUBROUTINE PRINTROUTINE(STR,N)
!DEC$ ATTRIBUTES DLLEXPORT :: PRINTROUTINE
CHARACTER(LEN=N) :: STR
PRINT *, STR
END SUBROUTINE

SUBROUTINE LOGICALROUTINE(LOGICVAR)
!DEC$ ATTRIBUTES DLLEXPORT :: LOGICALROUTINE
LOGICAL LOGICVAR(3)
PRINT *, LOGICVAR
END SUBROUTINE

먼저 첫번째 루틴은 정수형태의 입력값이며, 세번째 루틴은 CHARACTER 와 정수타입의 입력값을 갖습니다. 마지막 루틴은 LOGICAL 형태의 벡터를 갖습니다. 컴파일은 다음과 같은 명령어로 수행합니다.

> ifort /dll test.f90

2. Julia Usage
julia> N = Array{Int64}(1,1);
julia> N[1,1] = 10;
julia> M = Array{Int64}(1,1);
julia> M[1,1] = 20;
julia> K = Array{Int64}(1,1);
julia> ccall(("ADDROUTINE","test.dll"),Void,(Ptr{Int64},Ptr{Int64},Ptr{Int64}),N, M, K)

julia> X = Array{Float64}(2);
julia> X[1] = 10.0;
julia> X[2] = 20.0;
julia> Y = Array{Float64}(2);
julia> Y[1] = 2.0;
julia> Y[2] = 4.0;
julia> Z = Array{Float64}(2);
julia> ccall(("MULTROUTINE","test.dll"),Void,(Ptr{Float64},Ptr{Float64},Ptr{Float64}),X,Y,Z)

julia> STR = "test"
julia> N[1,1] = 4
julia> ccall(("PRINTROUTINE","test.dll"), Void, (Ptr{UInt8},Ptr{Int64}),STR,N)

julia> LOGICVAR = Array{Cint}(3);
julia> LOGICVAR[1] = 1;
julia> LOGICVAR[2] = 1;
julia> LOGICVAR[3] = 0;
julia> ccall(("LOGICALROUTINE","test.dll"), Void, (Ptr{Cint},),LOGICVAR)

3. Name Mangling
다양한 입출력 변수들의 형태들은 아래의 출처 링크에서 찾아 볼 수 있습니다. 그리고 유의할 점은 만약 입력변수가 하나라면 "(Ptr{Cint},)" 마지막에 콤마하나를 더 넣어줘야 정상 작동합니다.  컴파일이 되면서 Name Mangling이 일어나는데, 인텔 포트란에서 위에서 소개한 방식으로 컴파일 할 경우 "Upper Case" 로 Name Mangling이 일어납니다. 컴파일에 옵션을 주면 다른 형태로 Name Mangling 이 나타납니다.

 Name Mangling 이 복잡한 방식으로 작동되어서 함수의 이름을 모를경우 자신이 원하는 데로 지정해줄 수 있습니다. 함수이름은 다음과 같이 지정합니다.

MODULE HELLO_MODULE
USE iso_c_binding
IMPLICIT NONE
CONTAINS
SUBROUTINE HELLODLL() bind(C,name="HELLODLL")
!DEC$ ATTRIBUTES DLLEXPORT :: HELLODLL
PRINT *, "HELLODLLJIJIN"
END SUBROUTINE
END MODULE HELLO_MODULE

출처 - https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/#Calling-C-and-Fortran-Code-1

댓글

이 블로그의 인기 게시물

[Linux, AIX] 사용자 계정 생성 및 설정

[AIX] rpm 설치와 rpm 으로 패키지 설치 및 삭제

Ubuntu 에서 Fortran 시작하기