
How would one implement an CStringLen-style type that (a) was efficient, in particular could be read and written to Handles efficiently; (b) would get automatically deallocated by the Haskell garbage collector, when Haskell no longer referred to it; (c) was immutable, so that once created the character data could not be changed; (d) consequently had the property that conversion to and from String would be a pure operation; (e) could be passed to and from C using the FFI. (Of course C would need you to split the length and character data up; the character data would presumably have type "const char *".) ? It would be rather nice to have such a type.

How would one implement an CStringLen-style type that (a) was efficient, in particular could be read and written to Handles efficiently;
struct cstrlen { int refcount; // reference count int len; char* str; // or char str[0] using the usual gcc extension }
(b) would get automatically deallocated by the Haskell garbage collector, when Haskell no longer referred to it;
data Stub_CStringLen type CStringLen = ForeignPtr Stub_CStringLen -- or use newtype When you create a foreignptr to 'struct cstrlen' objects, you need to increment the refcount and when the foreignptr is freed, you decrement the reference counter and free if refcount == 0. (The reference count is to handle code that stores a pointer to an object in a C data structure and later returns it.)
(c) was immutable, so that once created the character data could not be changed;
don't provide any operations to mutate it
(d) consequently had the property that conversion to and from String would be a pure operation;
use unsafePerformIO to guarantee to Haskell that you have not provided any mutator operations
(e) could be passed to and from C using the FFI. (Of course C would need you to split the length and character data up; the character data would presumably have type "const char *".) ?
With the above, it is passed across as a single argument though you could deconstruct it if you want (take care with reference counts though). Other options may exist using packed string objects, pinning them in the GHC heap, etc. but they are not portable and probably not much more efficient. (I think you still need a reference count if you go down this path though, in this case, the count would track the number of pointers from C into Haskell instead of the other way around.) -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/
participants (2)
-
Alastair Reid
-
George Russell