将GHC ByteArray#复制到Ptr

时间:2016-09-25 20:16:36

标签: haskell ghc

我正在尝试编写以下函数:

memcpyByteArrayToPtr :: 
     ByteArray# -- ^ source
  -> Int -- ^ start
  -> Int -- ^ length
  -> Ptr a -- ^ destination
  -> IO ()

行为应该是在内部使用memcpyByteArray#的内容复制到Ptr。我做过这样的事情有两种技巧,但我很难推断他们的安全。

第一个在memory包中找到。辅助函数withPtr定义为:

data Bytes = Bytes (MutableByteArray# RealWorld)

withPtr :: Bytes -> (Ptr p -> IO a) -> IO a
withPtr b@(Bytes mba) f = do
    a <- f (Ptr (byteArrayContents# (unsafeCoerce# mba)))
    touchBytes b
    return a

但是,我非常确定这只是安全的,因为构建Bytes的唯一方法是使用调用newAlignedPinnedByteArray#的智能构造函数。 An answer given to a similar questiondocs for byteArrayContents#表示在处理固定ByteArray#时它是唯一安全的。在我的情况下,我正在处理ByteArray#uses internallytext,而且它们没有固定,所以我认为这样会不安全。

我遇到的第二种可能性是text本身。在Data.Text.Array source code的底部,有一个ffi函数memcpyI

foreign import ccall unsafe "_hs_text_memcpy" memcpyI
  :: MutableByteArray# s -> CSize -> ByteArray# -> CSize -> CSize -> IO ()

这由以下c代码支持:

void _hs_text_memcpy(void *dest, size_t doff, const void *src, size_t soff, size_t n)
{
  memcpy(dest + (doff<<1), src + (soff<<1), n<<1);
}

因为它是text的一部分,所以我相信这是安全的。它看起来很危险,因为它是从未固定的ByteArray#获取内存位置,这是byteArrayContents#文档警告的内容。我怀疑它没问题,因为ffi调用被标记为不安全,我认为这会阻止GC在ffi调用期间移动ByteArray#

这是我迄今为止所做的研究。到目前为止,我最好的猜测是我可以复制text中完成的内容。最大的区别在于,我不会传递MutableByteArray#ByteArray#作为两个指针,而是传递ByteArray#Ptr a(或者Addr# },我不确定你通常使用ffi中的哪一个。

我建议安全吗?有没有更好的方法可以让我避免使用ffi? base中有什么东西可以做到这一点吗?请随意更正我所做的任何错误假设,并感谢您的任何建议或指导。

1 个答案:

答案 0 :(得分:6)

copyByteArrayToPtr :: ByteArray# -> Int -> Ptr a -> Int -> ST s ()
copyByteArrayToPtr ba (I# x) (Ptr p) (I# y) = ST $ \ s ->
  (# copyByteArrayToAddr# ba x p y s, () #)

看起来像正确的primop。您只需要确保不要尝试将其复制到它占用的内存中。

你可能应该安全
Int#

不幸的是,文档并没有让我知道每个[56] [85,66,73] [57] [8,16] [25,96,22,17] [83,61] 应该是什么意思,但我想你可以通过试验和段错误来解决这个问题。