Редактировать: hCsound не имеет дело с этим конкретным случаем, поэтому я добавил полный пример ниже.
Возможно, вы захотите посмотреть на мой пакет hCsound (darcs repo ), который имеет дело с очень похожим случаем.
Обратите внимание, что очень важно, чтобы библиотека C не изменяла массивы, используемые Data.Vector.Storable.Vector
,Если вам нужно изменить данные, вы должны сначала скопировать старые данные, изменить массив через ffi и, наконец, обернуть указатели в новый вектор.
Вот код.Как было отмечено в комментарии, 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
Обратите внимание, что массив выделяетсяwithArray
, поэтому он автоматически gc'd после того, как функция вернется.
Эти массивы не заканчиваются нулем, поэтому вам нужно убедиться, что длина передана функции C некоторым другимМетод.
withForeignPtr
не используется.Вместо этого вызывается touchForeignPtr
, чтобы гарантировать, что ForeignPtr не был освобожден до завершения функции C.Чтобы использовать withForeignPtr
, вам нужно вложить вызовы для каждого внутреннего вектора.Вот что делает функция nest
в коде hCsound.Это гораздо сложнее, чем просто позвонить touchForeignPtr
.