2015-04-15 2 views
3

Я смотрю haskell-mpi binding, и у нас есть, например, эта подпись в mpi.h:c2hs in and out-type marshalling

int MPI_Initialized (int *flag); 

который в Internal.chs представлена ​​следующим образом:

{#fun unsafe Initialized as^{alloca- `Bool' peekBool*} -> `()' discard*- #} 

Q: У меня есть некоторые проблемы понимания того, что происходит вокруг входного параметра:

  • то, что - модификатор делает? Вики c2hs говорят, что «тип аргумента функции Hs определяется набором всех спецификаций сортировки, где в маршаллере не следует знак минуса», но я до сих пор его не понимаю.

  • функция C принимает указатель на int; что делает маршаллер вывода? AFAICT, он разыгрывает указатель и преобразует результат в Boolean. Это верно?

NB: префикс MPI_ вводится в именах функций по {# context prefix="MPI"#}.

NB2:

peekBool :: (Storable a, Num a, Eq a) => Ptr a -> IO Bool 
peekBool = liftM toBool . peek 

NB3: discard _ = return() и модификатор *- служит для запуска монадическое действия, но отбрасывая его результат

ответ

1

Я считаю, что самый простой способ понять, что делает 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, это действительно хороший способ понять, что происходит.