파생 타입과 struct(Derived Types and struct)

파생 타입과 struct(Derived Types and struct)

Fortran의 파생 타입(derived type)을 C의 struct와 호환되게 선언하는 방법을 설명하는 문서예요. BIND(C) 속성을 붙이면 C 쪽 구조체와 메모리 레이아웃이 맞아떨어져서, C와 Fortran 코드를 서로 넘나들며 데이터를 주고받을 수 있어요.

출처: Derived Types and struct (The GNU Fortran Compiler)

본문

파생 타입을 C의 struct와 호환되게 만들려면 타입 선언에 BIND(C) 속성을 사용하면 돼요. 예를 들어 아래와 같은 타입 선언이 있다고 해볼게요.

 USE ISO_C_BINDING
 TYPE, BIND(C) :: myType
   INTEGER(C_INT) :: i1, i2
   INTEGER(C_SIGNED_CHAR) :: i3
   REAL(C_DOUBLE) :: d1
   COMPLEX(C_FLOAT_COMPLEX) :: c1
   CHARACTER(KIND=C_CHAR) :: str(5)
 END TYPE

이건 C에서 다음과 같은 struct 선언과 대응돼요.

 struct {
   int i1, i2;
   /* Note: "char" might be signed or unsigned.  */
   signed char i3;
   double d1;
   float _Complex c1;
   char str[5];
 } myType;

여기서 핵심은 각 컴포넌트의 타입과 종류를 ISO_C_BINDING이 제공하는 C_INT, C_DOUBLE 같은 상호운용 타입으로 맞춰 주는 거예요. 그러면 C와 Fortran 쪽이 서로 같은 메모리 배치를 공유하게 돼요.

한 가지 조심할 점이 있어요. C 바인딩 속성(BIND(C))을 가진 파생 타입은 sequence 속성, 형 매개변수(type parameters), extends 속성, 바인딩된 절차(type-bound procedures)를 가질 수 없어요. 그리고 모든 컴포넌트는 상호운용 가능한 타입과 종류여야 하며, pointerallocatable 속성을 가질 수 없어요. 컴포넌트의 이름 자체는 상호운용성에 영향을 주지 않아요.

추가로, 비트 필드(bit field)나 가변 길이 배열 멤버를 가진 union이나 struct는 이에 직접 대응하는 Fortran 표현이 없기 때문에 상호운용이 불가능해요.

더 알아보기

  • BIND(C)의 전체 맥락(전역 변수, 서브루틴·함수, C 포인터 등)은 C와의 상호운용성(Interoperability with C) 문서에서 폭넓게 다뤄져요.
  • 각 컴포넌트에 쓸 수 있는 상호운용 타입 목록은 ISO_C_BINDING 내장 모듈 문서가 기준이 돼요.
  • 배열이 포함된 경우엔 CHARACTER(KIND=C_CHAR) :: str(5)처럼 크기까지 맞춰 줘야 C의 char str[5]와 대응돼요. 배열 차원의 순서(column-major)도 함께 확인하는 게 좋아요.