可存储的空数据声明

zmt*_*thy 9 haskell ffi ghc

我正在尝试为C库创建一个Haskell包装器.底层结构太复杂,不能表达为显式类型,除了在C函数之间传递之外,我实际上并没有使用它们,所以我用它EmptyDataDecls来让GHC为我工作.

我需要的是一个指向这些数据类型之一的指针,但是当我尝试用alloca它创建一个数据类型时,它会抱怨数据不属于该类型Storable.例如:

{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}

module Main where

import Foreign.Marshal.Alloc
import Foreign.Ptr

data Struct

foreign import ccall "header.h get_struct"
    get_struct :: Ptr Struct -> IO ()

main = alloca $ \ptr -> get_struct ptr
Run Code Online (Sandbox Code Playgroud)

GHC不会编译这个,说没有实例Storable Struct.我可以自己实现它:

instance Storable Struct where
    sizeOf _    = ...
    alignment _ = ...
Run Code Online (Sandbox Code Playgroud)

但这接近于击败目的 - 如果我不关心结构中的内容,我不想定义这样的事情.

我注意到指向指针的指针工作正常,因为Ptr类是Storable.所以我可以在调用之前使用peekon 来完成我的目标:ptrget_struct

main = alloca $ \ptr -> do
  ptr <- peek ptr
  get_struct ptr
Run Code Online (Sandbox Code Playgroud)

但这感觉就像一个黑客.

有没有办法在Storable不定义实例的情况下考虑空数据声明?

bdo*_*lan 6

如果您不知道它有多大,就无法分配.该函数是否会忽略其参数?然后传入一个空指针.否则,您需要为结构实际分配足够的空间 - 不要通过分配零字节或指针大小的缓冲区来切角,因为被调用的函数将写入缓冲区的末尾,从而破坏内存.

完成数据声明,或编写具有适当大小和对齐值的可存储实例; 没有办法以某种形式提供大小/对齐数据.

  • 请注意,您不必定义实例的每个方法.如果你不想将结构封送到Haskell,只需定义`sizeOf`和`alignment`,但留下`peek`和`poke` undefined(或调用错误). (3认同)
  • 您可以使用像chs这样的方便工具 - 它可以帮助您找出这些值. (2认同)