Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFI: How to declare `size_t`

Tags:

haskell

ffi

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?

like image 831
esato1981 Avatar asked Apr 18 '15 12:04

esato1981


1 Answers

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.

like image 132
kosmikus Avatar answered Oct 26 '22 14:10

kosmikus