Can the FFI deal with arrays? If so, how?

后端 未结 4 1258
终归单人心
终归单人心 2021-01-01 14:37

I\'m pretty sure it\'s possible to send arrays through the FFI, but I can\'t find any examples. For instance, I have a Haskell array that I send to a int foo(int*)

4条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-01 15:24

    If you use the Data.Vector library you could use Data.Vector.Storable for your needs. Then you can use functions such as unsafeToForeignPtr or unsafeWith to access the underlying foreign pointer. This allows you to call C-code without any copying or marshaling taking place.

    If you want to create a vector from a C-array you can use unsafeFromForeignPtr.

    For your examples you can use (assuming c_foo does not modify it's arguments)

    import Foreign.Ptr
    import Foreign.C.Types
    import System.IO.Unsafe (unsafePerformIO)
    import qualified Data.Vector.Storable as SV
    
    foreign import ccall unsafe "foo" c_foo :: Ptr CInt -> CInt
    
    haskellFoo :: SV.Vector CInt -> CInt
    haskellFoo sv = unsafePerformIO $
        SV.unsafeWith sv $ \ptr -> return (c_foo ptr)
    

    This can be be golfed to:

    haskellFoo sv = unsafePerformIO $
        SV.unsafeWith sv (return . c_foo)
    

    Note that if your C-function modifies the data, then you shouldn't do this, instead you should make a copy of the data to not break referential transparency.

    If you want to use the standard Array-type you could use withStorableArray from Data.Array.Storable in the same way.

提交回复
热议问题