summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-13 07:40:11 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-13 07:40:11 -0700
commit39855e5aa9ffd3eac89a8ada790fcb5555bc3f65 (patch)
tree405033c36a75a2fc1321ddd0904de8da9bfb5e5d /ffi.c
parent133f25494e54eb508a0f19c3abdcfc24ccc4c1ce (diff)
downloadtxr-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.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/ffi.c b/ffi.c
index d34a1bb6..055d88d1 100644
--- a/ffi.c
+++ b/ffi.c
@@ -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));