diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-04-27 06:36:09 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-04-27 06:36:09 -0700 |
commit | c489ea71dd23c4108bad92bba463cd153fc9135c (patch) | |
tree | eb99beed5624645ec5f8299dda9753ed878f345b | |
parent | 8b0fdf4d546dac440af65909eb81ecb2f7d767e9 (diff) | |
download | txr-c489ea71dd23c4108bad92bba463cd153fc9135c.tar.gz txr-c489ea71dd23c4108bad92bba463cd153fc9135c.tar.bz2 txr-c489ea71dd23c4108bad92bba463cd153fc9135c.zip |
ffi: sane in/out protocol; buffers work directly.
Fix incorrect memory allocation in (ptr-in buf)
and (ptr-in-out buf) passing.
Buffer arguments passed to a function as
(ptr-in buf) or (ptr-in-out buf) now pass the buffer
directly without allocating another copy, as in the
case of arrays or structs.
* ffi.c (struct txr_ffi_type): New members alloc, free.
The pointer types use these functions, together with fill,
for the management of the buffering of their target type.
(ffi_fixed_alloc, ffi_noop_free, ffi_buf_alloc,
ffi_ptr_in_in): New static functions.
(ffi_ptr_in_put): Use target type's alloc function,
rather than chk_malloc. A struct or array will actually
allocate the buffer needed for their C version. A buffer
will not; it will just return its internal pointer,
just like what the wstr type does with strings.
This function now sets up ffi_ptr_in_in as the in handler
for this pointer type, rather than ffi_freeing_in,
because the freeing has to go through the target type
interface, and not directly to free. Buffers use the
no-op free function.
(ffi_ptr_out_in): Use the target type's free function
rathr than free.
(ffi_ptr_out_put, ffi_ptr_in_out_put): Use the target type's
allocator instead of chk_malloc.
(make_ffi_type_pointer, make_ffi_type_struct,
make_ffi_type_array): Initialize the alloc and free function
pointer members of the txr_ffi_type struct.
(ffi_type_compile): Set up alloc and free for buffers.
-rw-r--r-- | ffi.c | 52 |
1 files changed, 46 insertions, 6 deletions
@@ -88,8 +88,10 @@ struct txr_ffi_type { cnum nelem; void (*put)(struct txr_ffi_type *, val obj, mem_t *dst, val self); val (*get)(struct txr_ffi_type *, mem_t *src, val self); - void (*fill)(struct txr_ffi_type *, mem_t *src, val obj, val self); void (*in)(struct txr_ffi_type *, val obj, val self); + mem_t *(*alloc)(struct txr_ffi_type *, val obj, val self); + void (*free)(void *); + void (*fill)(struct txr_ffi_type *, mem_t *src, val obj, val self); mem_t *buf; }; @@ -199,6 +201,18 @@ static void ffi_void_put(struct txr_ffi_type *tft, (void) self; } +static mem_t *ffi_fixed_alloc(struct txr_ffi_type *tft, val obj, val self) +{ + (void) obj; + (void) self; + return chk_malloc(tft->size); +} + +static void ffi_noop_free(void *ptr) +{ + (void) ptr; +} + static val ffi_void_get(struct txr_ffi_type *tft, mem_t *src, val self) { (void) tft; @@ -607,6 +621,12 @@ static val ffi_buf_get(struct txr_ffi_type *tft, mem_t *src, val self) return make_duplicate_buf(num(tft->nelem), p); } +static mem_t *ffi_buf_alloc(struct txr_ffi_type *tft, val buf, val self) +{ + (void) tft; + return buf_get(buf, self); +} + static void ffi_buf_fill(struct txr_ffi_type *tft, mem_t *src, val buf, val self) { @@ -614,15 +634,23 @@ static void ffi_buf_fill(struct txr_ffi_type *tft, mem_t *src, buf_fill(buf, src, self); } +static void ffi_ptr_in_in(struct txr_ffi_type *tft, val obj, val self) +{ + val tgttype = tft->mtypes; + struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); + tgtft->free(tft->buf); + tft->buf = 0; +} + static void ffi_ptr_in_put(struct txr_ffi_type *tft, val s, mem_t *dst, val self) { val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); - mem_t *buf = chk_malloc(tgtft->size); + mem_t *buf = tgtft->alloc(tgtft, s, self); tgtft->put(tgtft, s, buf, self); tft->buf = buf; - tft->in = ffi_freeing_in; + tft->in = ffi_ptr_in_in; } static void ffi_ptr_out_in(struct txr_ffi_type *tft, val obj, val self) @@ -631,7 +659,7 @@ static void ffi_ptr_out_in(struct txr_ffi_type *tft, val obj, val self) struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); if (tgtft->fill != 0) tgtft->fill(tgtft, tft->buf, obj, self); - free(tft->buf); + tgtft->free(tft->buf); tft->buf = 0; } @@ -640,7 +668,7 @@ static void ffi_ptr_out_put(struct txr_ffi_type *tft, { val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); - mem_t *buf = chk_malloc(tgtft->size); + mem_t *buf = tgtft->alloc(tgtft, s, self); tft->buf = buf; tft->in = ffi_ptr_out_in; *coerce(mem_t **, dst) = buf; @@ -659,7 +687,7 @@ static void ffi_ptr_in_out_put(struct txr_ffi_type *tft, { val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); - mem_t *buf = chk_malloc(tgtft->size); + mem_t *buf = tgtft->alloc(tgtft, s, self); tgtft->put(tgtft, s, buf, self); tft->buf = buf; tft->in = ffi_ptr_out_in; @@ -798,6 +826,8 @@ static val make_ffi_type_builtin(val syntax, val lisp_type, tft->size = tft->align = size; tft->put = put; tft->get = get; + tft->alloc = ffi_fixed_alloc; + tft->free = free; return obj; } @@ -823,6 +853,8 @@ static val make_ffi_type_pointer(val syntax, val lisp_type, tft->put = put; tft->get = get; tft->mtypes = tgtype; + tft->alloc = ffi_fixed_alloc; + tft->free = free; return obj; } @@ -852,6 +884,8 @@ static val make_ffi_type_struct(val syntax, val lisp_type, tft->mtypes = types; tft->put = ffi_struct_put; tft->get = ffi_struct_get; + tft->alloc = ffi_fixed_alloc; + tft->free = free; tft->fill = ffi_struct_fill; for (i = 0; i < nmemb; i++) { @@ -903,6 +937,8 @@ static val make_ffi_type_array(val syntax, val lisp_type, tft->mtypes = eltype; tft->put = ffi_array_put; tft->get = ffi_array_get; + tft->alloc = ffi_fixed_alloc; + tft->free = free; tft->fill = ffi_array_fill; for (i = 0; i < nelem; i++) @@ -994,6 +1030,8 @@ val ffi_type_compile(val syntax) &ffi_type_pointer, ffi_buf_put, ffi_buf_get); struct txr_ffi_type *tft = ffi_type_struct(type); + tft->alloc = ffi_buf_alloc; + tft->free = ffi_noop_free; tft->fill = ffi_buf_fill; tft->nelem = nelem; return type; @@ -1101,6 +1139,8 @@ val ffi_type_compile(val syntax) &ffi_type_pointer, ffi_buf_put, ffi_void_get); struct txr_ffi_type *tft = ffi_type_struct(type); + tft->alloc = ffi_buf_alloc; + tft->free = ffi_noop_free; tft->fill = ffi_buf_fill; return type; } else if (syntax == void_s) { |