Я считаю, что самый простой способ понять, что делает C2HS, чтобы посмотреть на созданный им код Haskell. В этом случае функция крючок
{#fun unsafe Initialized as^{alloca- `Bool' peekBool*} -> `()' discard*- #}
результаты в следующем коде Haskell (слегка прибиралась):
initialized :: IO Bool
initialized =
alloca $ \a ->
initialized'_ a >>= \res ->
discard res >>
peekBool a
foreign import ccall unsafe "Control/Parallel/MPI/Internal.chs.h MPI_Initialized"
initialized'_ :: Ptr CInt -> IO CInt
Здесь «-
» после ИАС для входного аргумента в функции крюка означает, что этот аргумент фактически не фигурирует в качестве аргумента для полученной функции Haskell - в этом случае происходит то, что некоторое пространство выделяется для аргумента MPI_Initialized
(с использованием alloca
), функция C вызывается с использованием указателя на этот выделенное пространство, а выход функции Haskell - retu rned, используя peekBool
, чтобы извлечь значение из выделенного пространства.
Тип функции Haskell, которую производит C2HS, равен IO Bool
, то есть параметр «вход» не появляется нигде. (Документация C2HS действительно говорит об этом, но довольно сложно понять, что это означает, пока вы не увидите пример!)
Выходной маршаллер просто отбрасывает результат вызова функции MPI_Initialized
C, которая это код статуса, который не очень интересен в этом случае. Результат real возвращает результат из кода Haskell, который производит C2HS, генерируется выходным маршаллером для аргумента указателя функции MPI_Initialized
. Функция peekBool
считывает целочисленное значение из указателя C int *
и преобразует его в Haskell Bool
; «*
» в маршаллере вывода означает, что это значение должно быть возвращено в монаде IO
.
Эта модель распределения с «-
» в качестве входного ИАС, какой-то функции «прятки» с «IO *
» в качестве выходного ИАС (и часто discaring возвращаемое значение функции C, как хорошо) является довольно распространенным явлением. Многие библиотеки C используют этот шаблон назначения результатов через указатели, и отслеживание выделения указателей вручную в Haskell вызывает раздражение, поэтому C2HS пытается помочь вам в управлении этим. Требуется некоторое время, чтобы привыкнуть к тому, где положить все «-
» и «*
», но, глядя на код Haskell, который генерирует C2HS, это действительно хороший способ понять, что происходит.