我试图从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
不可移植,对吧?
问题是您CSize
作为抽象类型导入.FFI允许类型的newtype-wrapped版本Word64
,但仅当它实际上可以看到包含的类型时.
在您的情况下,将适当的导入行更改为
import Foreign.C.Types (CSize(..))
Run Code Online (Sandbox Code Playgroud)
应该做的伎俩.