expose strlen from Foreign.C.String

Andrew Martin andrew.thaddeus at gmail.com
Fri Jan 22 21:56:33 UTC 2021


>
> Are you suggesting that it should have an "IO Int" result type to force
> sequencing?  Is this warranted?
>

Yes. This is warranted. That's why Foreign.Storable.peek has IO in its
result type. On any CString with a finite lifetime, it is necessary to
sequence any reads and writes, and IO is the way this is done in base. By
contrast, on a CString that is both immutable and has an infinite lifetime,
we do not need to sequence reads. What kinds of CStrings fit the bill? Only
those backed by primitive string literals. So, for example, if you have:

    myString :: CString
    myString = Ptr "foobar"#

Since, myString is backed by something in the rodata section of a binary
(meaning that it will never change and it will never be deallocated), then
we do not care if reads get floated around. There are no functions in base
for unsequenced reads, but in primitive, you'll find
Data.Primitive.Ptr.indexOffPtr, which is unsequenced. So something like
this would be ok:

    someOctet :: Word8
    someOctet = Data.Primitive.Ptr.indexOffPtr myString 3

The cstringLength# in GHC.CString is similar to indexOffPtr. In fact, it
could be implemented using indexOffPtr. The reason that cstringLength#
exists (and in base of all places) is so that a built-in rewrite rule
perform this transformation:

    cstringLength "foobar"#
    ==>
    6#

This will eventually be used to great effect in bytestring. See
https://github.com/haskell/bytestring/pull/191.

To get back to the original question, I think that any user-facing
cstringLength
function should probably be:

    cstringLength :: CString -> IO Int

We need a separate FFI call that returns its result in IO to accomplish
this. But
this just be done in base rather than ghc-prim. There are no interesting
rewrite
rules that exist for such a function.

On Fri, Jan 22, 2021 at 3:31 PM Viktor Dukhovni <ietf-dane at dukhovni.org>
wrote:

> On Fri, Jan 22, 2021 at 08:45:54AM -0500, Andrew Martin wrote:
>
> > x <- malloc ...
> > memcpy ... copy a nul-terminated string into x
> > let len = cstringLength x
> > free x
>
> Isn't this broadly true for general uses of CString?  Which is why we
> have `withCString`:
>
>
> https://hackage.haskell.org/package/base-4.14.1.0/docs/Foreign-C-String.html#v:withCString
>
> Is there any particularly different about the proposed `cstringLength`?
>
> Are you suggesting that it should have an "IO Int" result type to force
> sequencing?  Is this warranted?  Shouldn't users of CString (Ptr CChar)
> be already aware of the liveness issue in general.
>
> --
>     Viktor.
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>


-- 
-Andrew Thaddeus Martin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20210122/9825040a/attachment.html>


More information about the Libraries mailing list