ale*_*tor 6 haskell vector ffi
我正在为ac库做一个简单的包装器,它需要有一个传递给它的向量列表.它需要一组指向数组的指针.为了建立一个漂亮的界面,我想要Vector的Vector(或列表),但我无法真正找到如何在idiomatic haskell中做到这一点.(或任何其他方式比memcopying周围的东西).
我正在寻找的是类似的东西
Vector (Vector Foo) -> (Ptr (Ptr Foo) -> IO a) -> IO a
Run Code Online (Sandbox Code Playgroud)
编辑:hCsound 不处理这种确切的情况,所以我在下面添加了一个完整的示例。
您可能想查看我的包hCsound ( darcs repo ),它必须处理非常相似的情况。
请注意,C 库不会修改Data.Vector.Storable.Vector. 如果确实需要修改数据,则应先复制旧数据,然后通过 ffi 修改数组,最后将指针包装到新的 Vector 中。
这是代码。正如评论中指出的那样,Data.Vector.Storable.Vector它本身没有 Storable 实例,因此您需要外部向量为Data.Vector.Vector.
import Foreign.Storable
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Marshal.Array
import qualified Data.Vector as V
import qualified Data.Vector.Storable as S
import Data.Vector.Storable.Internal
withPtrArray v f = do
let vs = V.map S.unsafeToForeignPtr v -- (ForeignPtr, Offset, Length)
ptrV = V.toList $ V.map (\(fp,off,_) -> offsetToPtr fp off) vs
res <- withArray ptrV f
V.mapM_ (\(fp,_,_) -> touchForeignPtr fp) vs
return res
Run Code Online (Sandbox Code Playgroud)
请注意,该数组是由 分配的withArray,因此在函数返回后会自动进行 gc 处理。
这些数组不是以 null 终止的,因此您需要确保通过其他方法将长度传递给 C 函数。
withForeignPtr没有被使用。相反,touchForeignPtr调用它以确保在 C 函数完成之前不释放ForeignPtr。为了使用withForeignPtr,您需要为每个内部向量嵌套调用。这就是nesthCsound 代码中的函数的作用。它比仅仅调用要复杂得多touchForeignPtr。