Immutable CStrings

Alastair Reid alastair@reid-consulting-uk.ltd.uk
Wed, 23 Apr 2003 18:07:12 +0100


> 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/