<div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Are you suggesting that it should have an "IO Int" result type to force sequencing? Is this warranted?<br></blockquote><br>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:<br><br> myString :: CString<br> myString = Ptr "foobar"#<br><br>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:<br><br> someOctet :: Word8<br> someOctet = Data.Primitive.Ptr.indexOffPtr myString 3<br><br>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:<br><br> cstringLength "foobar"#<br> ==><br> 6#<br><br>This will eventually be used to great effect in bytestring. See <a href="https://github.com/haskell/bytestring/pull/191">https://github.com/haskell/bytestring/pull/191</a>.<br><br>To get back to the original question, I think that any user-facing cstringLength<br>function should probably be:<br><br> cstringLength :: CString -> IO Int<br><br>We need a separate FFI call that returns its result in IO to accomplish this. But<br>this just be done in base rather than ghc-prim. There are no interesting rewrite<br>rules that exist for such a function.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jan 22, 2021 at 3:31 PM Viktor Dukhovni <<a href="mailto:ietf-dane@dukhovni.org">ietf-dane@dukhovni.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Fri, Jan 22, 2021 at 08:45:54AM -0500, Andrew Martin wrote:<br>
<br>
> x <- malloc ...<br>
> memcpy ... copy a nul-terminated string into x<br>
> let len = cstringLength x<br>
> free x<br>
<br>
Isn't this broadly true for general uses of CString? Which is why we<br>
have `withCString`:<br>
<br>
<a href="https://hackage.haskell.org/package/base-4.14.1.0/docs/Foreign-C-String.html#v:withCString" rel="noreferrer" target="_blank">https://hackage.haskell.org/package/base-4.14.1.0/docs/Foreign-C-String.html#v:withCString</a><br>
<br>
Is there any particularly different about the proposed `cstringLength`?<br>
<br>
Are you suggesting that it should have an "IO Int" result type to force<br>
sequencing? Is this warranted? Shouldn't users of CString (Ptr CChar)<br>
be already aware of the liveness issue in general.<br>
<br>
-- <br>
Viktor.<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail_signature">-Andrew Thaddeus Martin</div>