String Haskell中是否有类似字符串的数据类型实现在普通内存缓冲区之上,以避免在使用C时转换?

String Haskell中是否有类似字符串的数据类型实现在普通内存缓冲区之上,以避免在使用C时转换?,string,performance,haskell,ffi,String,Performance,Haskell,Ffi,为了提高FFI的效率,我希望直接使用包含C函数生成的字符串的缓冲区,而无需通过peekCString复制和转换到String,如中所示(参见下面的代码) 是否有类似于String的类型?使用标准的字符串函数,也许还能够根据字符串文本进行模式匹配 也许是这群人中的某个 我已经完成了w.r.t.内存管理,我需要一个ForeignPtr(让垃圾收集器释放已分配用于保存外部函数创建的数据的未使用缓冲区) 引用的代码示例 使用peekCString: -- ------------------------

为了提高FFI的效率,我希望直接使用包含C函数生成的字符串的缓冲区,而无需通过
peekCString
复制和转换到
String
,如中所示(参见下面的代码)

是否有类似于
String
的类型?使用标准的字符串函数,也许还能够根据字符串文本进行模式匹配

也许是这群人中的某个

我已经完成了w.r.t.内存管理,我需要一个
ForeignPtr
(让垃圾收集器释放已分配用于保存外部函数创建的数据的未使用缓冲区)

引用的代码示例 使用peekCString:

-- -----------------------------------------------------------------------------
-- fd{Read,Write}

-- | Read data from an 'Fd' and convert it to a 'String' using the locale encoding.
-- Throws an exception if this is an invalid descriptor, or EOF has been
-- reached.
fdRead :: Fd
       -> ByteCount -- ^How many bytes to read
       -> IO (String, ByteCount) -- ^The bytes read, how many bytes were read.
fdRead _fd 0 = return ("", 0)
fdRead fd nbytes = do
    allocaBytes (fromIntegral nbytes) $ \ buf -> do
    rc <- fdReadBuf fd buf nbytes
    case rc of
      0 -> ioError (ioeSetErrorString (mkIOError EOF "fdRead" Nothing Nothing) "EOF")
      n -> do
       s <- peekCStringLen (castPtr buf, fromIntegral n)
       return (s, n)

-- | Read data from an 'Fd' into memory.  This is exactly equivalent
-- to the POSIX @read@ function.
fdReadBuf :: Fd
          -> Ptr Word8 -- ^ Memory in which to put the data
          -> ByteCount -- ^ Maximum number of bytes to read
          -> IO ByteCount -- ^ Number of bytes read (zero for EOF)
fdReadBuf _fd _buf 0 = return 0
fdReadBuf fd buf nbytes =
  fmap fromIntegral $
    throwErrnoIfMinus1Retry "fdReadBuf" $
      c_safe_read (fromIntegral fd) (castPtr buf) nbytes

foreign import ccall safe "read"
   c_safe_read :: CInt -> Ptr CChar -> CSize -> IO CSsize
——-----------------------------------------------------------------------------
--fd{读,写}
--|从“Fd”读取数据,并使用区域设置编码将其转换为“字符串”。
--如果这是无效的描述符或EOF已被删除,则引发异常
--达到。
fdRead::Fd
->字节数--^要读取多少字节
->IO(字符串,字节计数)--^读取的字节数,读取的字节数。
fdRead _fd0=返回(“,0”)
fdRead fd nbytes=do
allocaBytes(从整数n字节)$\buf->do
rc ioError(ioeseterroString(mkIOError EOF“fdRead”Nothing“EOF”)
n->do
s Ptr Word8--^要在其中放置数据的内存
->字节计数--^要读取的最大字节数
->IO字节数--^读取的字节数(EOF为零)
fdReadBuf\u fd\u buf 0=返回0
fdReadBuf fd buf N字节=
fmap积分$
抛出器rNOIFMINUS1重试“fdReadBuf”$
c_安全读取(来自积分fd)(castPtr buf)n字节
国外进口ccall安全“读取”
c_安全读取::CInt->Ptr CChar->CSize->IO CSsize

如果您正在考虑
CString
s,最接近的高级数据类型可能是bytestring,尤其是模块的使用。@bheklillr谢谢!看起来和我需要的差不多。我将进一步探讨是否存在与
unsafePackMallocCString
类似的“安全”变体(因为如果某个东西被称为“不安全”,我假设存在一个更安全但效率更低的变体),以及类似于“与cstring的低级别交互”的事情是否可以通过
文本来完成(如果我想正确使用Unicode)…由于您正在进行低级编程,因此这是可以使用不安全函数的时候之一,但是您的上覆API应该使它们的使用安全。例如,您可以使用
unsafePackMallocCString
创建
ByteString
,但决不允许指针转义使用
unsafepackmallocstring
的任何函数的范围。令人担忧的是,在将ByteString传递给纯函数后,底层内存可能会被修改,从而破坏了纯函数,但如果你从未让指针到达某个可能戳到它的地方,那么你会更安全。或者,您可以在项目中为
ReadOnlyCString
或类似的东西编写一个模块,在您使用的外部类型周围使用newtype包装器,但只导出用于读取该内存位置的值的函数。这会很棘手,但这是可能的。@bheklir如果将
unsafePackMallocCString cstr
包装成
unsafePerfmormIO
?因为我知道给定一个常数
cstr
,无论我调用它多少次,结果总是相同的(从
String
-编程的角度来看)。我是否希望,只要在计算中不再有可能使用它,就会正确地对生成的
ByteString
进行垃圾收集和释放?。。