4

haskell-mpi bindingを見ていると、たとえば次のような署名がありmpi.hます:

int MPI_Initialized (int *flag); 

これInternal.chsは次のように表されます。

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

Q: 入力パラメータの周りで何が起こっているのか理解できません:

  • -モディファイヤは何をしているの?c2hs wiki には、「Hs 関数の引数の型は、in マーシャラーの後にマイナス記号が続かないすべてのマーシャリング仕様のセットによって決定される」と書かれていますが、まだわかりません。

  • C 関数は へのポインタを取りますint。出力マーシャラーは何をしていますか? AFAICT、ポインターを逆参照し、結果をブール値に変換します。これは正しいです?

注意:MPI_プレフィックスは、関数名で a によって導入されます{# context prefix="MPI"#}

注意2:

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

NB3: discard _ = return ()*-修飾子はモナド アクションを実行するのに役立ちますが、その結果は破棄されます

4

1 に答える 1

2

C2HS の機能を理解する最も簡単な方法は、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 関数が呼び出されpeekBool、割り当てられたスペースから値を抽出するために Haskell 関数の出力が返されます。

C2HS が生成する Haskell 関数の型は だけですIO Bool。つまり、"input" パラメータはどこにも表示されません。(C2HS のドキュメントにはこのように書かれていますが、例を見るまでそれが何を意味するのかを理解するのは非常に困難です!)

出力マーシャラーは、MPI_InitializedC 関数への呼び出しの結果を破棄するだけです。これは、この場合はあまり興味深いステータス コードではありません。C2HS が生成する Haskell コードからの実際のMPI_Initialized戻り値は、関数へのポインター引数の出力マーシャラーによって生成されます。このpeekBool関数は、C ポインターから整数値を読み取り、int *それを Haskell に変換しBoolます。*出力マーシャラーの " " は、この値がIOモナドで返される必要があることを意味します。

-入力マーシャラーとして " " を使用し、出力マーシャラーとして "IO " を使用したある種の "peek" 関数*(および C 関数の戻り値を破棄することも多い) を使用したこの割り当てパターンは、非常に一般的です。多くの C ライブラリは、ポインターを介して結果を割り当てるこのパターンを使用しており、Haskell で手動でポインター割り当てを追跡するのは煩わしいため、C2HS はその管理を支援しようとします。-すべての " " と " "を配置する場所に慣れるにはしばらく時間がかかりますが*、C2HS が生成する Haskell コードを見ると、何が起こっているのかを理解するのに非常に役立ちます。

于 2015-04-19T19:29:31.493 に答える