diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-05-13 07:40:11 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-05-13 07:40:11 -0700 |
commit | 39855e5aa9ffd3eac89a8ada790fcb5555bc3f65 (patch) | |
tree | 405033c36a75a2fc1321ddd0904de8da9bfb5e5d /ffi.c | |
parent | 133f25494e54eb508a0f19c3abdcfc24ccc4c1ce (diff) | |
download | txr-39855e5aa9ffd3eac89a8ada790fcb5555bc3f65.tar.gz txr-39855e5aa9ffd3eac89a8ada790fcb5555bc3f65.tar.bz2 txr-39855e5aa9ffd3eac89a8ada790fcb5555bc3f65.zip |
ffi: use dynamic allocation for wstr and wstr-d.
The direct pointer use of the wstr type causes problems
for callbacks. Plus allowing the foreign world to retain
the pointers into string objects is inherenty unsafe.
We can introduce an "unsafe wstr" type in a later release
for efficiency.
* ffi.c (ffi_wstr_in): New function.
(ffi_wstr_put): Removed by ffi_wstr_d_put rename.
(ffi_wstr_d_put): Renamed to ffi_wstr_put: both wstr and
wstr-d strings have a dynamically-allocating put.
(ffi_init_types): Give wstr type ffi_wstr_in handler.
wstr-d type's registration switched to ffi_wstr_put,
which is just ffi_wstr_d_put renamed.
* txr.1: Memory management notes for wstr updated.
Diffstat (limited to 'ffi.c')
-rw-r--r-- | ffi.c | 34 |
1 files changed, 21 insertions, 13 deletions
@@ -618,15 +618,15 @@ static val ffi_str_d_get(struct txr_ffi_type *tft, mem_t *src, val self) return ret; } -static void ffi_wstr_put(struct txr_ffi_type *tft, val s, mem_t *dst, - val self) +static val ffi_wstr_in(struct txr_ffi_type *tft, int copy, + mem_t *src, val obj, val self) { - if (s == nil) { - *coerce(const wchar_t **, dst) = 0; - } else { - const wchar_t *ws = c_str(s); - *coerce(const wchar_t **, dst) = ws; - } + wchar_t **loc = coerce(wchar_t **, src); + if (copy) + obj = if2(*loc, string(*loc)); + free(*loc); + *loc = 0; + return obj; } static val ffi_wstr_get(struct txr_ffi_type *tft, mem_t *src, val self) @@ -635,7 +635,7 @@ static val ffi_wstr_get(struct txr_ffi_type *tft, mem_t *src, val self) return p ? string(p) : 0; } -static void ffi_wstr_d_put(struct txr_ffi_type *tft, val s, mem_t *dst, +static void ffi_wstr_put(struct txr_ffi_type *tft, val s, mem_t *dst, val self) { if (s == nil) { @@ -1689,12 +1689,20 @@ static void ffi_init_types(void) ffi_typedef(str_d_s, make_ffi_type_builtin(str_d_s, str_s, sizeof (mem_t *), &ffi_type_pointer, ffi_str_put, ffi_str_d_get)); - ffi_typedef(wstr_s, make_ffi_type_builtin(wstr_s, str_s, - sizeof (mem_t *), &ffi_type_pointer, - ffi_wstr_put, ffi_wstr_get)); + { + val type = ffi_typedef(wstr_s, make_ffi_type_builtin(wstr_s, str_s, + sizeof (mem_t *), + &ffi_type_pointer, + ffi_wstr_put, + ffi_wstr_get)); + struct txr_ffi_type *tft = ffi_type_struct(type); + tft->in = ffi_wstr_in; + ffi_typedef(wstr_s, type); + } + ffi_typedef(wstr_d_s, make_ffi_type_builtin(wstr_d_s, str_s, sizeof (mem_t *), &ffi_type_pointer, - ffi_wstr_d_put, ffi_wstr_d_get)); + ffi_wstr_put, ffi_wstr_d_get)); ffi_typedef(bstr_d_s, make_ffi_type_builtin(bstr_d_s, str_s, sizeof (mem_t *), &ffi_type_pointer, ffi_bstr_put, ffi_bstr_d_get)); |