Foreign.StablePtr — Haskell 값에 대한 안정 참조
Foreign.StablePtr — Haskell 값에 대한 안정 참조
Foreign.StablePtr은 Haskell 값에 대한 '안정 참조(stable pointer)'를 제공하는 모듈이에요. 일반적인 Haskell 참조는 가비지 컬렉션 중에 재배치될 수 있지만, 안정 참조는 그렇지 않아서 외부(주로 C) 코드에 안전하게 넘겨줄 수 있어요. C 코드는 이것을 Haskell 값에 대한 불투명한(opaque) 참조로 취급할 수 있어요. 이 모듈은 안정 참조를 만들고, 해제하고, 다시 Haskell 값으로 되돌리고, 주소로 변환하는 기능을 담고 있어요.
본문
이 모듈이 내보내는 것들은 다음과 같아요.
module Foreign.StablePtr (
StablePtr, newStablePtr, deRefStablePtr, freeStablePtr,
castStablePtrToPtr, castPtrToStablePtr
) where
36.1 Haskell 값에 대한 안정 참조
data StablePtr a
안정 포인터는 가비지 컬렉션의 영향을 받지 않음이 보장되는 Haskell 표현식에 대한 참조예요. 즉, 가비지 컬렉션 중에 해제되지도 않고 안정 포인터 자체의 값이 변하지도 않아요(보통의 참조는 가비지 컬렉션 중에 재배치될 수 있어요). 따라서 안정 포인터는 외부 코드에 전달될 수 있고, 외부 코드는 그것을 Haskell 값에 대한 불투명한 참조로 취급할 수 있어요. StablePtr a 타입의 값은 타입 a의 Haskell 표현식에 대한 안정 포인터예요.
instance Eq (StablePtr a) instance Storable (StablePtr a)
newStablePtr :: a -> IO (StablePtr a)
주어진 Haskell 값을 가리키는 안정 포인터를 만들어요.
deRefStablePtr :: StablePtr a -> IO a
안정 포인터가 참조하는 Haskell 값을 얻어요. 즉, 대응하는 makeStablePtr 호출에 전달되었던 바로 그 값을 돌려줘요. 만약 deRefStablePtr의 인자가 freeStablePtr로 이미 해제되었다면 그 동작은 정의되지 않아요.
freeStablePtr :: StablePtr a -> IO ()
안정 포인터와 Haskell 값 사이의 연관 관계를 해제해요. 이후에 그 안정 포인터를 deRefStablePtr이나 freeStablePtr에 전달하면 동작이 정의되지 않아요. 하지만 안정 포인터는 여전히 castStablePtrToPtr에 전달될 수 있는데, 이 경우 그 함수가 돌려주는 Foreign.Ptr.Ptr () 값은 정의되지 않아요(특히 Foreign.Ptr.nullPtr일 수도 있어요). 그럼에도 castStablePtrToPtr 호출 자체는 발산(divergence)하지 않음이 보장돼요.
castStablePtrToPtr :: StablePtr a -> Ptr ()
안정 포인터를 주소로 강제 변환(coerce)해요. 원래의 안정 포인터를 castPtrToStablePtr로 되찾을 수 있다는 점을 제외하면 결과 값에 대한 보장은 없어요. 특히, 그 주소는 접근 가능한 메모리 위치를 가리키지 않을 수도 있고, 그 주소를 Foreign.Storable.Storable 클래스의 멤버 함수에 전달하는 것은 정의되지 않은 동작을 일으킬 수 있어요.
castPtrToStablePtr :: Ptr () -> StablePtr a
castStablePtrToPtr의 역함수예요. 즉 다음의 항등식이 성립해요.
sp == castPtrToStablePtr (castStablePtrToPtr sp)
아직 freeStablePtr이 실행되지 않은 임의의 안정 포인터 sp에 대해 위 식이 성립해요. 게다가 castPtrToStablePtr은 오직 castStablePtrToPtr이 만들어 낸 포인터에만 적용해야 해요.
36.1.1 C 쪽 인터페이스
Haskell 코드와 상호 운용하는 C 프로그램은 헤더 HsFFI.h를 포함할 때 다음 정의를 사용할 수 있어요.
typedef void ⋆HsStablePtr;