Foreign.Marshal.Utils — 범용 마샬링 유틸리티

Foreign.Marshal.Utils — 범용 마샬링 유틸리티

Foreign.Marshal.Utils는 Haskell 값과 C 메모리 사이를 오갈 때 반복적으로 쓰이는 '마샬링(marshalling)' 동작들을 묶어 놓은 모듈이에요. 메모리를 임시로 할당하고 값을 채워 넣는 동작을 하나로 합친 with, 그리고 불리언·Maybe 값이나 객체 목록을 다루는 편의 함수들이 여기 모여 있어요. 여기서 마샬링이란 Haskell 데이터를 외부(주로 C) 언어가 이해하는 메모리 표현으로 옮기거나, 그 반대로 읽어 오는 일을 말해요. 이 모듈을 쓰면 FFI 코드에서 반복되는 할당·해제·포인터 변환 패턴을 간결하게 다룰 수 있어요.

출처: Haskell 2010 언어 리포트

본문

이 모듈이 내보내는(export) 것들은 다음과 같아요.

module Foreign.Marshal.Utils (

    with,  new,  fromBool,  toBool,  maybeNew,  maybeWith,  maybePeek,

    withMany,  copyBytes,  moveBytes

  ) where

34.1 범용 마샬링 유틸리티

34.1.1 할당과 마샬링의 결합

with :: Storable a => a -> (Ptr a -> IO b) -> IO b

with val f는, val을 마샬링해서 담아 둔 임시 할당 메모리 블록을 가리키는 포인터를 인자로 전달하며 계산 f를 실행해요(이는 allocapoke를 합친 동작이에요). 이 메모리는 f가 끝나면(정상 종료든 예외든) 해제되므로, f에 전달된 포인터는 그 이후에 사용하면 안 돼요.

new :: Storable a => a -> IO (Ptr a)

메모리 블록을 할당하고 그 안에 값을 마샬링해요(이는 mallocpoke를 합친 동작이에요). 할당되는 영역의 크기는 해당 타입에 대한 Storable 인스턴스의 Foreign.Storable.sizeOf 메서드로 결정돼요. 더 이상 필요 없을 때는 Foreign.Marshal.Alloc.freeForeign.Marshal.Alloc.finalizerFree로 메모리를 해제할 수 있어요.

34.1.2 불리언 값의 마샬링(0이 아닌 값이 True에 대응)

fromBool :: Num a => Bool -> a

Haskell의 Bool을 수치 표현으로 변환해요.

toBool :: Num a => a -> Bool

수치 표현의 불리언을 Haskell 값으로 변환해요.

34.1.3 Maybe 값의 마샬링

maybeNew :: (a -> IO (Ptr a)) -> Maybe a -> IO (Ptr a)

저장 공간을 할당하고 Maybe로 감싸인 Storable 값을 마샬링해요. Nothing을 나타내는 데는 nullPtr이 사용돼요.

maybeWith :: (a -> (Ptr b -> IO c) -> IO c)   -> Maybe a -> (Ptr b -> IO c) -> IO c

withXXX 결합자를 Maybe로 감싸인 값을 마샬링하는 결합자로 바꿔 주는데, NothingnullPtr로 표현해요.

maybePeek :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)

peek 결합자를, nullPtr에 적용되면 Nothing을 돌려주는 결합자로 변환해요.

34.1.4 Storable 객체 목록의 마샬링

withMany :: (a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res

withXXX 결합자를 객체 목록 전체로 확장해서, 마샬링된 객체들의 목록을 만들어 내요.

34.1.5 memcpy와 memmove의 Haskell식 인터페이스

(인자 순서: 목적지, 원본)

copyBytes :: Ptr a -> Ptr a -> Int -> IO ()

두 번째 영역(원본)에서 첫 번째 영역(목적지)으로 주어진 바이트 수만큼 복사해요. 다만 복사되는 두 영역은 겹치면 안 돼요.

moveBytes :: Ptr a -> Ptr a -> Int -> IO ()

두 번째 영역(원본)에서 첫 번째 영역(목적지)으로 주어진 바이트 수만큼 복사해요. 복사되는 두 영역은 겹칠 수 있어요.

더 알아보기 (Learn more)