[gambit-list] Converting (unsigned char *) into u8vector?

Marc Feeley feeley at iro.umontreal.ca
Tue May 19 12:15:49 EDT 2009


On 18-May-09, at 10:30 PM, Taylor Venable wrote:

> I have some binary data which is stored in an (unsigned char *) and I
> want to convert it into a u8vector.  So I tried writing a conversion
> function like this:
>
> ___SCMOBJ BYTEARRAY_to_SCMOBJ (unsigned char *src, ___SCMOBJ *dst,  
> int arg_num)
> {
>    unsigned char *srcp = src;
>    unsigned int size;
>    int i = 0;
>
>    bcopy(src, &size, sizeof(unsigned int));
>    src += sizeof(unsigned int);
>
>    ___SCMOBJ ___err = ___FIX(___NO_ERR);
>    ___BEGIN_ALLOC_U8VECTOR(size);
>
>    for (i = 0; i < size; i += 1) {
>        ___SCMOBJ scm_int;
>
>        ___err = ___EXT(___U8_to_SCMOBJ) (src[i], &scm_int, arg_num);
>
>        if (___err != ___FIX(___NO_ERR))
>            return ___FIX(___UNKNOWN_ERR);
>
>        ___ADD_U8VECTOR_ELEM(i, scm_int);
>        ___EXT(___release_scmobj) (scm_int);
>    }
>
>    ___END_ALLOC_U8VECTOR(size);
>    dst = ___GET_U8VECTOR(size);
>    return ___FIX(___NO_ERR);
> }
>
> (This function will be used by macros to support c-define-type.  I'm
> storing the size of the array in the first sizeof(int) bytes, like a
> "Pascal string" does.)
>
> By looking through gambit.h I found some macros which seem to apply to
> making and manipulating u8vectors, such as ___ADD_U8VECTOR_ELEM.
> However, they use a variable ___hp which isn't defined anywhere.  Is
> this the right API to use for this sort of thing?  Or if not hopefully
> somebody can share an example of this kind of conversion that I can
> use as a guide.


The ___BEGIN_ALLOC_xxx macros defined in gambit.h allocate "movable"  
objects from the heap.  They are meant to be called from code  
generated by the Gambit Scheme compiler, where ___hp (the heap  
pointer) is in scope.  These macros should not be called from user  
code because some tricky invariants must be maintained when using  
movable objects.

Instead you should call ___alloc_scmobj and specify with the last  
parameter that a "still" object (which is not moved by the GC) is  
requested.  This avoids some garbage collection issues.

So the code should look like this (untested):


___SCMOBJ BYTEARRAY_to_SCMOBJ (unsigned char *src, ___SCMOBJ *dst, int  
arg_num)
{
    unsigned int size;
    ___SCMOBJ obj;

    bcopy(src, &size, sizeof(unsigned int));

    src += sizeof(unsigned int);

    obj = ___EXT(___alloc_scmobj) (___sU8VECTOR, size, ___STILL);

    if (___FIXNUMP(obj)) /* heap overflow? */
      {
        *dst = ___FAL;
        return ___FIX(___CTOS_HEAP_OVERFLOW_ERR+arg_num);
      }

    bcopy(src, ___BODY(obj), size);

    *dst = obj;

    return ___FIX(___NO_ERR);
}

Marc



More information about the Gambit-list mailing list