
How do people like to set up their foreign I/O functions to return ByteStrings? I was a little stumped over this yesterday evening, while trying to write ` recv :: Socket -> Int -> Int -> ByteString ' Doc says `Byte vectors are encoded as strict Word8 arrays of bytes, held in a ForeignPtr, and can be passed between C and Haskell with little effort.' Which sounds perfect - I'm always up for `little effort'! CString doesn't seem like the right thing for socket results, because the data shouldn't be NUL-terminated, and I might want to realloc when the returned data doesn't fill the buffer. I don't see any other Ptr-related function or constructor in the documentation - am I missing something there? Thanks, Donn Cave, donn@drizzle.com

On Sun, 2006-11-12 at 10:49 -0800, Donn Cave wrote:
How do people like to set up their foreign I/O functions to return ByteStrings? I was a little stumped over this yesterday evening, while trying to write ` recv :: Socket -> Int -> Int -> ByteString '
Doc says `Byte vectors are encoded as strict Word8 arrays of bytes, held in a ForeignPtr, and can be passed between C and Haskell with little effort.' Which sounds perfect - I'm always up for `little effort'!
CString doesn't seem like the right thing for socket results, because the data shouldn't be NUL-terminated, and I might want to realloc when the returned data doesn't fill the buffer. I don't see any other Ptr-related function or constructor in the documentation - am I missing something there?
packCStringLen :: CStringLen -> ByteString (type CStringLen = (Ptr CChar, Int)) http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-ByteString.h... So if you know the length and the pointer to the beginning of the buffer then it's just packCStringLen (ptr, len) Of course you're not allowed to change the buffer after this, if you are using a mutable buffer then you'll have to make a copy: copyCStringLen :: CStringLen -> IO ByteString Duncan

donn:
How do people like to set up their foreign I/O functions to return ByteStrings? I was a little stumped over this yesterday evening, while trying to write ` recv :: Socket -> Int -> Int -> ByteString '
Doc says `Byte vectors are encoded as strict Word8 arrays of bytes, held in a ForeignPtr, and can be passed between C and Haskell with little effort.' Which sounds perfect - I'm always up for `little effort'!
CString doesn't seem like the right thing for socket results, because the data shouldn't be NUL-terminated, and I might want to realloc when the returned data doesn't fill the buffer. I don't see any other Ptr-related function or constructor in the documentation - am I missing something there?
And for custom data (not just C strings), if the withCString* functions don't quite fit, you can always pack the foreign Ptr into a ByteString by stepping inside the ByteString constructor: http://www.haskell.org/haskellwiki/Wc#Going_via_C -- Don

On Mon, 13 Nov 2006, Donald Bruce Stewart wrote:
And for custom data (not just C strings), if the withCString* functions don't quite fit, you can always pack the foreign Ptr into a ByteString by stepping inside the ByteString constructor:
That's actually what I tried first, but in this particular situation (ghc-6.4.1 / fps-0.7), PS apparently isn't exported? The CStringLen approach works, except that the allocated data doesn't get garbage-collected. Just for the sake of experiment I tried a regular CString with packMallocCString, and that didn't leak nearly as much memory - but still some, in a simple loop where "pack" doesn't leak anything. Thanks, Donn Cave, donn@drizzle.com

donn:
On Mon, 13 Nov 2006, Donald Bruce Stewart wrote:
And for custom data (not just C strings), if the withCString* functions don't quite fit, you can always pack the foreign Ptr into a ByteString by stepping inside the ByteString constructor:
That's actually what I tried first, but in this particular situation (ghc-6.4.1 / fps-0.7), PS apparently isn't exported?
Right, you'll want to grab the soon-to-be-tagged fps 0.8, which matches that provided with ghc 6.6. It's in the darcs repo.
The CStringLen approach works, except that the allocated data doesn't get garbage-collected. Just for the sake of experiment I tried a regular CString with packMallocCString, and that didn't leak nearly as much memory - but still some, in a simple loop where "pack" doesn't leak anything.
-- Don
participants (3)
-
Donn Cave
-
dons@cse.unsw.edu.au
-
Duncan Coutts