如何为此类型创建可存储实例?

时间:2015-04-19 18:06:37

标签: haskell binding ffi

假设我有以下C结构:

typedef struct _Ready {
    int ready;
} *Ready;

我使用这种类型在Haskell中表示它:

data Ready = Ready { ready :: CInt }

现在我想要一个Storable实例。以下工作正常:

instance Storable Ready where
    alignment = sizeOf
    sizeOf _  = (#size Ready)

但是,添加peekpoke的任何定义都会失败:

    peek p = Ready <$> (#peek Ready, ready) p   -- FAILS
    poke p (Ready r) = (#poke Ready, ready) p r -- FAILS

错误归结为ready不属于结构或联合:

/usr/lib/ghc-7.10.1/template-hsc.h:72:24:
  error: request for member ‘ready’ in something not a structure or union

我做错了什么?

谢谢!

2 个答案:

答案 0 :(得分:7)

Ready(C类型)不是结构或联合,它是指向struct _Ready的指针。您应该使用struct _Ready,例如

peek p = Ready <$> (#peek struct _Ready, ready) p
poke p (Ready r) = (#poke struct _Ready, ready) p r

此外,您的sizeOf方法错误,需要进行相同的更改。您需要结构的大小,但是您当前具有指向结构的指针的大小,并且它们在64位系统上通常不相同。

答案 1 :(得分:1)

我无法确切地说出你做错了什么,因为我从来没有偶然发现你正在使用的所有哈希标志。但以下应该可以解决问题:

instance Storable Ready where
    alignment _ = alignment (undefined :: CInt)
    sizeOf _ = sizeOf (undefined :: CInt)
    peek p = Ready <$> peekByteOff p 0
    poke p (Ready r) = pokeByteOff p 0 r

0peekByteOff的{​​{1}}参数只反映pokeByteOff类型的ready组件(在C中)是第一个字段记录。我对定义_Readyalignment并不十分肯定,但我希望你能展示另一种可能性。