我目前正在编写Haskell绑定到GEGL库,它最初是用C编写的。这是我第一次使用FFI,所以我可能错过了一些东西。
我的问题是,我在这样的代码中得到了段错误:
-- | Simple iteration over a rectangle section of a buffer.
iterateOver
:: GeglBuffer -- ^ Target buffer
-> GeglRectangle -- ^ Rectangle to iterate over
-> BablFormat -- ^ Pixel format
-> GeglAccessMode -- ^ Access mode to pixel data
-> GeglAbyssPolicy -- ^ Abbyss policy for pixel data
-> (Pixel -> Pixel) -- Function to apply to each pixel
-> IO ()
iterateOver buf rect form am ap func = do
traceIO "start"
(FFI.GeglBufferIterator iterPtr) <- gegl_buffer_iterator_new buf rect form am ap
traceIO "new iterator"
untilM_ (do
floats <- map (\(CFloat f) -> f) <$> FFI.c_gegl_peek_data iterPtr -- Code breaks here
traceIO "peeked data"
let ops = buildPixelList rect floats
nps = map func ops
nfl = map CFloat $ buildFloatList nps
FFI.c_gegl_poke_data iterPtr nfl
traceIO "poked data"
) ( not <$> gegl_buffer_iterator_next (FFI.GeglBufferIterator iterPtr))
traceIO "finished"
c_gegl_peek_data
函数已使用inline-c
编写,如下所示:
-- | Get the list of pixel data out of a 'GeglBufferIterator'.
c_gegl_peek_data
:: GeglBufferIteratorDummy -- ^ Iterator to take data from
-> IO [CFloat]
c_gegl_peek_data ptr = do
fptr <- [C.block| float * {
GeglBufferIterator * cptr = $(void * ptr);
float * a = (float *) cptr->data[0];
return a;
}|]
(CInt length) <- [C.block| int {
GeglBufferIterator * cptr = $(void * ptr);
int a = cptr->length;
return a;
}|]
peekArray (fromIntegral length :: Int) fptr
你们有人可以指出我的错误在哪里吗?
提前致谢。
修改
这是一个同样问题的小型自包含示例。它只需要inline-c
包。
{-#LANGUAGE QuasiQuotes #-}
{-#LANGUAGE OverloadedStrings #-}
{-#LANGUAGE TemplateHaskell #-}
{-#LANGUAGE ForeignFunctionInterface #-}
module Main where
import qualified Language.C.Inline as C
import Foreign.Marshal.Array
import Debug.Trace
main :: IO ()
main = do
traceIO "start"
ptr <- [C.block| int * {
int a[5] = {0,1,2,3,4};
return a;
}|]
traceIO "got pointer"
a <- peekArray 5 ptr
traceIO "peeked pointer"
putStrLn $ show a
traceIO "finish"
此外,我为此示例添加了cabal文件:
name: sandbox
version: 0.0.0.0
synopsis: Small example
author: nek0
maintainer: nek0@nek0.eu
build-type: Simple
cabal-version: >=1.10
executable sandbox
hs-source-dirs: app
main-is: Main.hs
c-sources: app/Main.c
ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, inline-c
default-language: Haskell2010