fun

fun

lib 안에 있는 fun 선언은 C 함수에 바인딩돼요.

lib C
  # In C: double cos(double x)
  fun cos(value : Float64) : Float64
end

바인딩하면 이 함수는 클래스 메서드처럼 C 타입 안에서 쓸 수 있어요:

C.cos(1.5) # => 0.0707372

파라미터가 없는 함수라면 괄호를 생략할 수 있어요(호출할 때도 생략):

lib C
  fun getch : Int32
end

C.getch

반환 타입이 void라면 생략할 수 있어요:

lib C
  fun srand(seed : UInt32)
end

C.srand(1_u32)

가변 인자 함수에도 바인딩할 수 있어요:

lib X
  fun variadic(value : Int32, ...) : Int32
end

X.variadic(1, 2, 3, 4)

C 함수를 호출할 때는 (뒤에서 설명할 to_unsafe를 제외하면) 암시적 변환이 없다는 점을 기억하세요. 정확히 기대하는 타입을 넘겨야 해요. 정수와 실수의 경우 다양한 to_... 메서드를 쓸 수 있어요.

함수 이름 (Function names)

lib 정의 안의 함수 이름은 대문자로 시작할 수 있어요. 이는 메서드와 lib 밖의 함수 정의(소문자로 시작해야 함)와는 다른 점이에요.

Crystal의 함수 이름은 C에서의 이름과 다를 수 있어요. 아래 예시는 C 함수 이름 SDL_Init을 Crystal에서 LibSDL.init으로 바인딩하는 방법을 보여줘요.

lib LibSDL
  fun init = SDL_Init(flags : UInt32) : Int32
end

C 이름은 유효한 식별자가 아닌 이름을 쓰기 위해 따옴표로 감쌀 수 있어요:

lib LLVMIntrinsics
  fun ceil_f32 = "llvm.ceil.f32"(value : Float32) : Float32
end

이 방법은 C 함수에 더 짧고 좋은 이름을 주는 데도 쓸 수 있어요. C 함수 이름은 보통 길고 라이브러리 이름이 접두사로 붙는 경우가 많거든요.

C 바인딩에서의 타입 (Types in C Bindings)

C 바인딩에서 쓸 수 있는 타입은 다음과 같아요:

  • 기본 타입(Int8, ..., Int64, UInt8, ..., UInt64, Float32, Float64)
  • 포인터 타입(Pointer(Int32), Int32*로도 쓸 수 있어요)
  • 정적 배열(StaticArray(Int32, 8), Int32[8]로도 쓸 수 있어요)
  • 함수 타입(Proc(Int32, Int32), Int32 -> Int32로도 쓸 수 있어요)
  • 이전에 선언된 다른 struct, union, enum, type, alias
  • Void: 반환 값이 없음을 뜻해요.
  • NoReturn: Void와 비슷하지만, 컴파일러가 그 호출 뒤에는 어떤 코드도 실행될 수 없다고 이해해요.
  • @[Extern] 어노테이션이 붙은 Crystal struct

fun 타입의 표기법은 type grammar를 참고하세요.

표준 라이브러리는 int, short, size_t 같은 흔한 C 타입의 별칭을 담은 LibC lib을 정의해요. 바인딩에서 이렇게 쓰세요:

lib MyLib
  fun my_fun(some_size : LibC::SizeT)
end

NOTE: C의 char 타입은 Crystal에서 UInt8이에요. 그래서 char*const char*UInt8*예요. Crystal의 Char 타입은 유니코드 코드포인트라 4바이트로 표현돼서, UInt8이 아니라 Int32에 가까워요. 헷갈리면 LibC::Char 별칭도 있어요.

출처: Crystal 공식 문서

더 알아보기 (Learn more)