9

我正在尝试为 C 库创建一个 Haskell 包装器。底层结构过于复杂,无法表示为显式类型,除了在 C 函数之间传递之外,我实际上并没有使用它们,所以我EmptyDataDecls让 GHC 为我解决问题。

我需要的是一个指向这些数据类型之一的指针,但是当我尝试用它创建一个时,alloca它抱怨数据不是 type 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

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

instance Storable Struct where
    sizeOf _    = ...
    alignment _ = ...

但这接近于违背目的 - 如果我不关心结构中的内容,我不想定义这些东西。

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

main = alloca $ \ptr -> do
  ptr <- peek ptr
  get_struct ptr

不过,这感觉像是一种黑客行为。

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

4

2 回答 2

6

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

要么完成数据声明,要么编写一个具有适当大小和对齐值的 Storable 实例;无法以某种形式提供大小/对齐数据。

于 2011-01-25T14:37:07.933 回答
2

这是另一种可能对您有用的方法。我假设您可以访问定义您需要分配的对象的所有 C 头文件。如果这是真的,您可以编写一层薄薄的 C 代码来分配和释放 C 对象。然后,您的 Haskell 代码可以调用这些 C 函数,而 Haskell 代码无需知道指针背后的内容。当 Haskell 的垃圾收集器知道不再需要对象时,Haskell 也可以自动调用空闲代码。

于 2011-01-26T02:16:19.693 回答