summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-04-27 06:36:09 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-04-27 06:36:09 -0700
commitc489ea71dd23c4108bad92bba463cd153fc9135c (patch)
treeeb99beed5624645ec5f8299dda9753ed878f345b
parent8b0fdf4d546dac440af65909eb81ecb2f7d767e9 (diff)
downloadtxr-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.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/ffi.c b/ffi.c
index 022030dd..7ab4a270 100644
--- a/ffi.c
+++ b/ffi.c
@@ -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) {