我正在尝试从外部C库绑定到C函数,该库返回指向内存缓冲区的指针和缓冲区的长度:
extern int myfunc(int arg1, unsigned char **buffer, size_t *buffer_len);
我尝试了以下代码但结果出现了分段错误。
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign
import Foreign.C.Types (CInt(..), CUChar(..), CSize(..))
import Foreign.Ptr (Ptr)
import Foreign.Marshal.Array (peekArray)
foreign import ccall unsafe "myfunc" c_myfunc :: CInt -> Ptr (Ptr CUChar) -> Ptr CSize -> IO (CInt)
getBuffer :: Int -> IO [CUChar]
getBuffer arg1 = do
alloca $ \buffer -> do
alloca $ \buflen -> do
res <- c_myfunc (CInt arg1) buffer buflen
buflen' <- fromIntegral <$> peek buflen
cs <- peekArray buflen' buffer -- return a [Ptr CUChar] of size buflen
cs' <- mapM peek cs -- return a [CUChar] of size buflen
return cs'
我认为peekArray确实分配了足够的内存,所以我不确定它出错的地方。欢迎任何帮助。
答案 0 :(得分:1)
愚蠢的错误,我错过了一个解除引用的步骤。此代码现在有效:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign
import Foreign.C.Types (CInt(..), CUChar(..), CSize(..))
import Foreign.Ptr (Ptr)
import Foreign.Marshal.Array (peekArray)
foreign import ccall unsafe "myfunc" c_myfunc :: CInt -> Ptr (Ptr CUChar) -> Ptr CSize -> IO (CInt)
getBuffer :: Int -> IO [CUChar]
getBuffer arg1 = do
alloca $ \ ptrbuf -> do
alloca $ \buflen -> do
res <- c_myfunc (CInt arg1) ptrBuf buflen
buflen' <- fromIntegral <$> peek buflen
buffer <- peek ptrBuf -- I MISSED THIS ONE. Extra dereferencing needed.
peekArray buflen' buffer -- return a [CUChar] of size buflen'