[gambit-list] How to properly allocate foreign object?

Marc Feeley feeley at iro.umontreal.ca
Sat Apr 11 09:53:58 EDT 2020


> On Apr 11, 2020, at 6:16 AM, Jörg F. Wittenberger <Joerg.Wittenberger at softeyes.net> wrote:
> 
> Thanks for your reply.
> 
> On Fri, 10 Apr 2020 15:49:15 -0400
> Marc Feeley <feeley at iro.umontreal.ca> wrote:
> 
>> There are a few issues with your code.  First of all, you should use
>> “___return(…);” to return a result (the assignment to
>> ___result_voidstar is deprecated).
> 
> OK.  Is there some documentation wrt. these things?

The Gambit manual (doc/gambit.pdf) has this to say:

When c-name-or-code is not a valid C identifier, it is treated as an arbitrary piece of C code. Within the C code the variables ‘___arg1’, ‘___arg2’, etc. can be referenced to access the converted arguments. Note that the C return statement can’t be used to return from the procedure. Instead, the ___return macro must be used. A procedure whose result-type is not void must pass the procedure’s result as the single argument to the ___return macro, for example ‘___return(123);’ to return the value 123. When result-type is void, the ___return macro must be called without a parameter list, for example ‘___return;’.

> 
>> An alternative would be to create your own type with a release
>> function, but that is probably overkill in this situation.
> 
> Interesting: you consider a type with release function to be the
> overkill?  I had the impression that the use of wills would be the
> overly complex way.
> 
> Nevertheless:  In your suggestion you still use malloc to allocate.  I
> do see situations where I'd tend to do this too.  Still I wonder if it
> was cheaper/faster to allocate on the Scheme heap.  And if so, how?

In your C code you could allocate a “still” u8vector object using:

___SCMOBJ obj = ___EXT(___alloc_scmobj) (___PSTATE, ___sU8VECTOR, length_in_bytes);

 /*
  * '___alloc_scmobj (___ps, subtype, bytes)' allocates a permanent or
  * still Scheme object (depending on '___ps') of subtype ‘subtype'
  * with a body containing 'bytes' bytes, and returns it as an encoded
  * Scheme object.  When '___ps' is NULL, a permanent object is
  * allocated, and when '___ps' is not NULL, a still object is
  * allocated in the heap of that processor's VM.  The initialization
  * of the object's body must be done by the caller.  In the case of
  * still objects this initialization must be done before the next
  * allocation is requested.  The 'refcount' field of still objects is
  * initially 1.  A fixnum error code is returned when there is an
  * error.
  */

and then decrement the reference count so that in the future the Gambit garbage collector will be solely responsible for determining if the object can be reclaimed:

___EXT(___release_scmobj) (obj);

To access the content of the object you can use the ___BODY(obj) macro to get a pointer to the content of the object:

  char *body = ___CAST(char*,___BODY(obj));
  body[0] = 11;
  body[1] = 22;

I don’t know if there is a significant performance difference between this and the other method I explained (but it does a single call to malloc rather than two).  You’ll have to benchmark it to see which one is faster.

Marc





More information about the Gambit-list mailing list