I am trying to compile an example from Real World Haskell (chapter 26):
There is a C
function I want to call using 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 */
Here's the haskell code that tries to import it:
{-# 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 ()
When I try to compile it ghc
gives the following error message:
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 ()
What type should I use to marshal a size_t
? If I replace CSize
and use Word64
instead it will compile, but Word64
is not portable, right?
The problem is that you imported CSize
as an abstract type. The FFI allows newtype-wrapped versions of types such as Word64
, but only if it can actually see the contained types.
In your case, changing the appropriate import line to
import Foreign.C.Types (CSize(..))
should do the trick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With