编写Haskell FFI用于读取系统调用

时间:2016-11-03 20:58:45

标签: linux haskell system-calls ffi

read函数的定义如下:

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t len)

我想为此编写一个Haskell FFI。这是我的尝试(没有编译):

foreign import ccall unsafe "read" c_read :: CInt -> Ptr () -> CSize -> IO CSsize

read :: Int -- ^ file descriptor
     -> Int64 -- ^ Bytes to allocate
     -> Word64 -- ^ Read upto this many bytes
     -> IO (String, Int64)
read fd bytes len = do
  allocaBytes (fromIntegral bytes) (\ptr -> do
                       size <- c_read (fromIntegral fd) ptr (fromIntegral len)
                       dat <- peekByteOff (castPtr ptr) (fromIntegral size) :: IO String
                       return (dat, (fromIntegral size))
                    )

它没有编译,因为Storable没有String的实例。有关如何为此编写FFI的任何提示?

2 个答案:

答案 0 :(得分:1)

Foreign.C.String是传统解决方案。

答案 1 :(得分:1)

根据Michael Snoyman和Reid Barton的建议,我终于想出了这个解决方案:

foreign import ccall safe "read" c_read :: CInt -> Ptr () -> CSize -> IO CSsize

read :: Int -- ^ file descriptor
     -> Int64 -- ^ Bytes to allocate
     -> Word64 -- ^ Read upto this many bytes
     -> IO (ByteString, Int64)
read fd bytes len = do
  (ptr :: Ptr ()) <- mallocBytes (fromIntegral bytes)
  size <- c_read (fromIntegral fd) ptr (fromIntegral len)
  bstring <- packCStringLen (castPtr ptr, fromIntegral size) 
  free ptr
  return (bstring, (fromIntegral size))