gpt4 book ai didi

haskell - 如何使用 Haskell 和 FFI 与 C 枚举进行交互?

转载 作者:行者123 更新时间:2023-12-02 04:21:35 26 4
gpt4 key购买 nike

假设 charm.c 有一个枚举 key 和一个返回 key 类型值的函数 get_key()

如何公开相应的 Haskell Key 记录和函数 getKey::IO Key

如果不手动指定每个枚举值如何映射到 Haskell 值,我该如何做到这一点?

最佳答案

对于@KevinReid,以下是如何使用 c2hs 执行此操作的示例.

给定枚举 key在文件charm.h中(我不知道枚举中有什么,所以我只填写了一些值)

typedef enum
{
PLAIN_KEY = 0,
SPECIAL_KEY = 1,
NO_KEY = 2
}
key;

key get_key();

您可以像这样使用 c2hs 的枚举钩子(Hook):

{#enum key as Key {underscoreToCase} deriving (Eq, Show)#}

要绑定(bind)到函数,您可以使用 callfuncall更简单,但不做任何编码。以下是两者的示例。 ffi 包裹的 get_key将返回 CInt,因此您需要手动编码(marshal)它(如果使用 call )或指定编码(marshal)器(如果使用 fun )。 c2hs 不包括枚举编码器,因此我在这里编写了自己的编码器:

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(稍作清理):

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)

关于haskell - 如何使用 Haskell 和 FFI 与 C 枚举进行交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6689969/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com