diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-04-29 12:26:26 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-04-29 12:26:26 -0700 |
commit | 5c9f482790a97c075d75d903e35a4cf7f09134c2 (patch) | |
tree | 9c8e4b88126049f024c1d8ea7564bd58b6805cf6 | |
parent | cced80ab687b521a1d07e53e1be70a33ea711d0f (diff) | |
download | txr-5c9f482790a97c075d75d903e35a4cf7f09134c2.tar.gz txr-5c9f482790a97c075d75d903e35a4cf7f09134c2.tar.bz2 txr-5c9f482790a97c075d75d903e35a4cf7f09134c2.zip |
ffi: ptr types map between nil and null pointers.
On the way out, if a ptr or ptr-in type encounters nil, it
passes a null pointer. On the way in, a null C pointer
received by a ptr type turns to the nil object.
* ffi.c (ffi_ptr_in_put, ffi_ptr_in_d_put, ffi_ptr_out_put,
ffi_ptr_put): Check for nil, and put out null pointer in that
case. (ffi_ptr_out_get, ffi_ptr_out_d_get): Check for null
pointer coming in and turn to nil.
-rw-r--r-- | ffi.c | 49 |
1 files changed, 33 insertions, 16 deletions
@@ -716,9 +716,13 @@ static void ffi_ptr_in_put(struct txr_ffi_type *tft, val s, mem_t *dst, val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); mem_t *buf = tgtft->alloc(tgtft, s, self); - tgtft->put(tgtft, s, buf, rtvec, self); - rtvec[tft->rtidx] = buf; - *coerce(mem_t **, dst) = buf; + if (s == nil) { + *coerce(mem_t **, dst) = rtvec[tft->rtidx] = 0; + } else { + tgtft->put(tgtft, s, buf, rtvec, self); + rtvec[tft->rtidx] = buf; + *coerce(mem_t **, dst) = buf; + } } static void ffi_ptr_in_d_put(struct txr_ffi_type *tft, val s, mem_t *dst, @@ -726,10 +730,15 @@ static void ffi_ptr_in_d_put(struct txr_ffi_type *tft, val s, mem_t *dst, { val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); - mem_t *buf = tgtft->alloc(tgtft, s, self); - (void) rtvec; - tgtft->put(tgtft, s, buf, rtvec, self); - *coerce(mem_t **, dst) = buf; + + if (s == nil) { + *coerce(mem_t **, dst) = 0; + } else { + mem_t *buf = tgtft->alloc(tgtft, s, self); + (void) rtvec; + tgtft->put(tgtft, s, buf, rtvec, self); + *coerce(mem_t **, dst) = buf; + } } static void ffi_ptr_out_in(struct txr_ffi_type *tft, val obj, @@ -749,9 +758,13 @@ static void ffi_ptr_out_put(struct txr_ffi_type *tft, val s, mem_t *dst, { val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); - mem_t *buf = tgtft->alloc(tgtft, s, self); - rtvec[tft->rtidx] = buf; - *coerce(mem_t **, dst) = buf; + if (s == nil) { + *coerce(mem_t **, dst) = rtvec[tft->rtidx] = 0; + } else { + mem_t *buf = tgtft->alloc(tgtft, s, self); + rtvec[tft->rtidx] = buf; + *coerce(mem_t **, dst) = buf; + } } static val ffi_ptr_out_get(struct txr_ffi_type *tft, mem_t *src, val self) @@ -759,7 +772,7 @@ static val ffi_ptr_out_get(struct txr_ffi_type *tft, mem_t *src, val self) val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); mem_t *ptr = *coerce(mem_t **, src); - return tgtft->get(tgtft, ptr, self); + return ptr ? tgtft->get(tgtft, ptr, self) : nil; } static val ffi_ptr_out_d_get(struct txr_ffi_type *tft, mem_t *src, val self) @@ -767,7 +780,7 @@ static val ffi_ptr_out_d_get(struct txr_ffi_type *tft, mem_t *src, val self) val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); mem_t *ptr = *coerce(mem_t **, src); - val ret = tgtft->get(tgtft, ptr, self); + val ret = ptr ? tgtft->get(tgtft, ptr, self) : nil; free(ptr); return ret; } @@ -777,10 +790,14 @@ static void ffi_ptr_put(struct txr_ffi_type *tft, val s, mem_t *dst, { val tgttype = tft->mtypes; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); - mem_t *buf = tgtft->alloc(tgtft, s, self); - tgtft->put(tgtft, s, buf, rtvec, self); - rtvec[tft->rtidx] = buf; - *coerce(mem_t **, dst) = buf; + if (s == nil) { + *coerce(mem_t **, dst) = 0; + } else { + mem_t *buf = tgtft->alloc(tgtft, s, self); + tgtft->put(tgtft, s, buf, rtvec, self); + rtvec[tft->rtidx] = buf; + *coerce(mem_t **, dst) = buf; + } } static void ffi_struct_walk(struct txr_ffi_type *tft, mem_t *ctx, |