to_unsafe
to_unsafe (C 타입으로의 자동 변환)
C 함수를 호출할 때마다 값을 일일이 변환하는 건 여간 번거로운 일이 아니에요. 타입에 to_unsafe 메서드를 정의해 두면, 그 값을 C 함수에 넘길 때 자동으로 이 메서드가 반환한 값을 전달해 줘요. C 타입 래퍼(wrapper)를 만들 때 아주 유용한 기법이에요.
본문
어떤 타입이 to_unsafe 메서드를 정의하고 있으면, 그 값을 C 함수에 전달할 때 이 메서드가 반환한 값이 전달돼요. 예시로 볼게요.
lib C
fun exit(status : Int32) : NoReturn
end
class IntWrapper
def initialize(@value : Int32)
end
def to_unsafe
@value
end
end
wrapper = IntWrapper.new(1)
C.exit(wrapper) # wrapper.to_unsafe가 Int32 타입인 C 함수에 전달돼요
이 방식은 C 타입의 래퍼를 정의할 때 그 값을 명시적으로 변환하지 않아도 되게 해 주기 때문에 아주 유용해요.
예를 들어, String 클래스는 UInt8*를 반환하는 to_unsafe를 구현하고 있어요.
lib C
fun printf(format : UInt8*, ...) : Int32
end
a = 1
b = 2
C.printf "%d + %d = %d\n", a, b, a + b
String을 그대로 C.printf에 넘겨도 되는 이유가 바로 to_unsafe 덕분이에요. 문자열 내부의 포인터(UInt8*)가 자동으로 전달되니까, 개발자가 직접 변환할 필요가 없죠.
더 알아보기
to_unsafe가 unsafe한 이유를 포함해 안전하지 않은 코드 전반은 Unsafe code에서 확인할 수 있어요.lib에서 C 함수를 선언하는 방법은 C 바인딩 문서를 참고하세요.