FFI:如何声明`size_t`

esa*_*981 7 haskell ffi

我试图从Real World Haskell编写一个例子(第26章):

有一个C我想要调用的函数FFI:

#include <stdint.h>
#include <sys/types.h>

/* only accepts uint32_t aligned arrays of uint32_t */
void hashword2(const uint32_t *key,  /* array of uint32_t */
           size_t length,        /* number of uint32_t values */
           uint32_t *pc,         /* in: seed1, out: hash1 */
           uint32_t *pb);        /* in: seed2, out: hash2 */
Run Code Online (Sandbox Code Playgroud)

这是尝试导入它的haskell代码:

{-# LANGUAGE BangPatterns, ForeignFunctionInterface #-}
import Data.Word (Word32, Word64)
import Foreign.C.Types (CSize)
import Foreign.Marshal.Utils (with)
import Foreign.Ptr (Ptr, castPtr, plusPtr)
import Foreign.Storable (Storable, peek, sizeOf)

foreign import ccall unsafe "lookup3.h hashword2" hashWord2
    :: Ptr Word32 -> CSize -> Ptr Word32 -> Ptr Word32 -> IO ()
Run Code Online (Sandbox Code Playgroud)

当我尝试编译它时,ghc会出现以下错误消息:

Unacceptable argument type in foreign declaration: CSize
When checking declaration:
  foreign import ccall unsafe "static lookup3.h hashword2" hashWord2
    :: Ptr Word32 -> CSize -> Ptr Word32 -> Ptr Word32 -> IO ()
Run Code Online (Sandbox Code Playgroud)

我应该用什么类型来编组size_t?如果我替换CSize并使用Word64它将编译,但Word64不可移植,对吧?

kos*_*kus 8

问题是您CSize作为抽象类型导入.FFI允许类型的newtype-wrapped版本Word64,但仅当它实际上可以看到包含的类型时.

在您的情况下,将适当的导入行更改为

import Foreign.C.Types (CSize(..))
Run Code Online (Sandbox Code Playgroud)

应该做的伎俩.

  • 并且7.10.1给出了更好的错误消息:"外部声明中不可接受的参数类型:'CSize'无法在外部调用中编组,因为其数据构造器不在范围内可能的修复:导入数据构造函数以使其进入范围" (2认同)