charm.cにenum key
があり、key
型の値を返す関数get_key()
があるとします。HaskellとFFIを使用してC enumとどのようにインタフェースしますか?
対応するHaskell Key
レコードと関数getKey :: IO Key
を公開するにはどうすればよいですか?
そして、どのように単一の列挙値がどのようにHaskell値にマッピングされるかを手動で指定することなく、これを行うにはどうすればよいですか?
charm.cにenum key
があり、key
型の値を返す関数get_key()
があるとします。HaskellとFFIを使用してC enumとどのようにインタフェースしますか?
対応するHaskell Key
レコードと関数getKey :: IO Key
を公開するにはどうすればよいですか?
そして、どのように単一の列挙値がどのようにHaskell値にマッピングされるかを手動で指定することなく、これを行うにはどうすればよいですか?
@KevinReidについては、c2hsでこれを行う方法の例です。
あなたはこのようc2hsの列挙型のフックを使用することができます(私は列挙型で何見当がつかないので、私はほんの数値で満たされた)ファイルcharm.h
に
typedef enum
{
PLAIN_KEY = 0,
SPECIAL_KEY = 1,
NO_KEY = 2
}
key;
key get_key();
を列挙key
を考える:
{#enum key as Key {underscoreToCase} deriving (Eq, Show)#}
関数にバインドするには、call
またはfun
のいずれかを使用できます。 call
は簡単ですが、マーシャリングは行いません。両方の例があります。 ffi-wrapped get_key
はCIntを返しますので、手動でマーシャリング(call
を使用する場合)またはマーシャラー(fun
を使用する場合)を指定する必要があります。
module Interface where -- file Interface.chs
{#enum key as Key {underscoreToCase} deriving (Eq, Show)#}
getKey = cIntToEnum `fmap` {#call get_key #}
{#fun get_key as getKey2 { } -> `Key' cIntToEnum #}
cIntToEnum :: Enum a => CInt -> a
cIntToEnum = toEnum . cIntConv
C2hsは(少しクリーンアップ)このことから、次のHaskellのが生成されます:私はここに私自身が書いたように、c2hsは、列挙型のマーシャラーが含まれていません
data Key = PlainKey
| SpecialKey
| NoKey
deriving (Eq,Show)
instance Enum Key where
fromEnum PlainKey = 0
fromEnum SpecialKey = 1
fromEnum NoKey = 2
toEnum 0 = PlainKey
toEnum 1 = SpecialKey
toEnum 2 = NoKey
toEnum unmatched = error ("Key.toEnum: Cannot match " ++ show unmatched)
getKey = cIntToEnum `fmap` get_key
getKey2 :: IO (Key)
getKey2 =
getKey2'_ >>= \res ->
let {res' = cIntToEnum res} in
return (res')
cIntToEnum :: Enum a => CInt -> a
cIntToEnum = toEnum . cIntConv
foreign import ccall safe "foo.chs.h get_key"
get_key :: (IO CInt)
foreign import ccall safe "foo.chs.h get_key"
getKey2'_ :: (IO CInt)
enumフックで定義されたenumのように、デフォルトのマーシャラが追加されました:https://github.com/haskell/c2hs/wiki/Implementation%20of%20Haskell%20Binding%20Modules。 – HaskellElephant
hsc2hsを、このためのマクロを持っています可能であればバニラ・ハスケルを使っています。 – mcandre
バニラ・ハスケルでは、すべて手作業で書くことはできません。 hsc2hsとc2hsは両方ともenumフックを持ち、bindings-dslはCPPマクロを使用します。これらはあなたのためにHaskell型とEnumインスタンスを自動生成しますが、バニラHaskellではありません。もちろん、あなたはそれを書き込むことができます。 c2hsを実行し、プリプロセッサを実行して、生成されたHaskellファイルを出力します。整列およびptrサイズ。 –
これを行うためにヘビーなツールが必要な理由は、enum定数はCのコンパイル時の構造体であり、ライブラリにリンクして取り出すことができるエクスポートシンボルではないため、enumsの値を発見するにはCソーステキスト。 –