FFI:如何声明 `size_t`

FFI: How to declare `size_t`

我正在尝试编译真实世界中的示例 Haskell(第 26 章):

我想使用 FFI:

调用一个 C 函数
#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 */

这是尝试导入它的 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 ()

当我尝试编译它时 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 ()

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

问题是您将 CSize 作为抽象类型导入。 FFI 允许类型的新类型包装版本,例如 Word64,但前提是它实际上可以看到包含的类型。

对于您的情况,将适当的导入行更改为

import Foreign.C.Types (CSize(..))

应该可以解决问题。