2015-04-18 12 views
6

Próbuję skompilować przykład z Real World Haskell (rozdział 26):FFI: Jak deklarują `size_t`

Jest C funkcja chcę zadzwonić używają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 */ 

Oto kod Haskell, który stara się go importować:

{-# 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() 

Gdy próbuję go skompilować ghc wydaje następujący komunikat o błędzie:

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() 

Jakiego typu powinienem użyć do przeprowadzenia size_t? Jeśli zastąpię CSize i użyję Word64 zamiast tego, skompiluje się, ale Word64 nie jest przenośny, prawda?

Odpowiedz

8

Problem polega na tym, że zaimportowano CSize jako typ abstrakcyjny. FFI zezwala na typy zapakowane w typ nowości, takie jak Word64, ale tylko wtedy, gdy rzeczywiście widzi zawarte w nich typy.

W twoim przypadku, zmieniając odpowiednią linię przywozowego

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

powinno załatwić sprawę.

+2

A 7.10.1 daje lepszy komunikat o błędzie: „nie do przyjęcia typ argumentu w obcym deklaracji: «cSize»nie może zostać zgromadzona w obcym rozmowy ponieważ jego konstruktor danych nie jest w zakres Możliwe fix: import danych do konstruktora przenieś go w zakres " –

+0

To się udało! Dzięki! – esato1981