summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi.c75
-rw-r--r--ffi.h4
2 files changed, 71 insertions, 8 deletions
diff --git a/ffi.c b/ffi.c
index cad0376d..7af6dda7 100644
--- a/ffi.c
+++ b/ffi.c
@@ -70,7 +70,9 @@ val void_s;
val struct_s;
-val wstr_s;
+val str_d_s, wstr_s, wstr_d_s;
+
+val buf_d_s;
val ptr_in_s, ptr_out_s, ptr_in_out_s;
@@ -601,11 +603,20 @@ static val ffi_str_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
(void) tft;
(void) self;
- const char *p;
- p = *coerce(const char **, src);
+ const char *p = *coerce(const char **, src);
return string_utf8(p);
}
+static val ffi_str_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
+{
+ (void) tft;
+ (void) self;
+ char *p = *coerce(char **, src);
+ val ret = string_utf8(p);
+ free(p);
+ return ret;
+}
+
static void ffi_wstr_put(struct txr_ffi_type *tft, val s, mem_t *dst,
mem_t *rtvec[], val self)
{
@@ -623,6 +634,23 @@ static val ffi_wstr_get(struct txr_ffi_type *tft, mem_t *src, val self)
return string(p);
}
+static void ffi_wstr_d_put(struct txr_ffi_type *tft, val s, mem_t *dst,
+ mem_t *rtvec[], val self)
+{
+ (void) tft;
+ (void) rtvec;
+ const wchar_t *ws = c_str(s);
+ *coerce(const wchar_t **, dst) = chk_strdup(ws);
+}
+
+static val ffi_wstr_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
+{
+ (void) tft;
+ (void) self;
+ wchar_t *p = *coerce(wchar_t **, src);
+ return string_own(p);
+}
+
static void ffi_buf_put(struct txr_ffi_type *tft, val buf, mem_t *dst,
mem_t *rtvec[], val self)
{
@@ -639,6 +667,22 @@ static val ffi_buf_get(struct txr_ffi_type *tft, mem_t *src, val self)
return make_duplicate_buf(num(tft->nelem), p);
}
+static void ffi_buf_d_put(struct txr_ffi_type *tft, val buf, mem_t *dst,
+ mem_t *rtvec[], val self)
+{
+ (void) rtvec;
+ mem_t *b = buf_get(buf, self);
+ *coerce(const mem_t **, dst) = chk_copy_obj(b, c_num(length(buf)));
+}
+
+static val ffi_buf_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
+{
+ (void) tft;
+ (void) self;
+ mem_t *p = *coerce(mem_t **, src);
+ return make_borrowed_buf(num(tft->nelem), p);
+}
+
static mem_t *ffi_buf_alloc(struct txr_ffi_type *tft, val buf, val self)
{
(void) tft;
@@ -1115,11 +1159,14 @@ val ffi_type_compile(val syntax)
&ffi_type_pointer,
ffi_ptr_in_out_put, ffi_ptr_out_get,
ffi_ptr_out_in, target_type);
- } else if (sym == buf_s) {
+ } else if (sym == buf_s || sym == buf_d_s) {
cnum nelem = c_num(cadr(syntax));
val type = make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
&ffi_type_pointer,
- ffi_buf_put, ffi_buf_get);
+ if3(sym == buf_s,
+ ffi_buf_put, ffi_buf_d_put),
+ if3(sym == buf_s,
+ ffi_buf_get, ffi_buf_d_get));
struct txr_ffi_type *tft = ffi_type_struct(type);
tft->alloc = ffi_buf_alloc;
tft->free = ffi_noop_free;
@@ -1228,14 +1275,25 @@ val ffi_type_compile(val syntax)
tft->in = ffi_freeing_in;
tft->rtsize = 1;
return type;
+ } else if (syntax == str_d_s) {
+ val type = make_ffi_type_builtin(syntax, str_s, sizeof (mem_t *),
+ &ffi_type_pointer,
+ ffi_str_put, ffi_str_d_get);
+ return type;
} else if (syntax == wstr_s) {
return make_ffi_type_builtin(syntax, str_s, sizeof (mem_t *),
&ffi_type_pointer,
ffi_wstr_put, ffi_wstr_get);
- } else if (syntax == buf_s) {
+ } else if (syntax == wstr_d_s) {
+ return make_ffi_type_builtin(syntax, str_s, sizeof (mem_t *),
+ &ffi_type_pointer,
+ ffi_wstr_d_put, ffi_wstr_d_get);
+ } else if (syntax == buf_s || syntax == buf_d_s) {
val type = make_ffi_type_builtin(syntax, buf_s, sizeof (mem_t *),
&ffi_type_pointer,
- ffi_buf_put, ffi_void_get);
+ if3(syntax == buf_s,
+ ffi_buf_put, ffi_buf_d_put),
+ ffi_void_get);
struct txr_ffi_type *tft = ffi_type_struct(type);
tft->alloc = ffi_buf_alloc;
tft->free = ffi_noop_free;
@@ -1427,7 +1485,10 @@ void ffi_init(void)
array_s = intern(lit("array"), user_package);
void_s = intern(lit("void"), user_package);
struct_s = intern(lit("struct"), user_package);
+ str_d_s = intern(lit("str-d"), user_package);
wstr_s = intern(lit("wstr"), user_package);
+ wstr_d_s = intern(lit("wstr-d"), user_package);
+ buf_d_s = intern(lit("buf-d"), user_package);
ptr_in_s = intern(lit("ptr-in"), user_package);
ptr_out_s = intern(lit("ptr-out"), user_package);
ptr_in_out_s = intern(lit("ptr-in-out"), user_package);
diff --git a/ffi.h b/ffi.h
index fafee40f..99c87a28 100644
--- a/ffi.h
+++ b/ffi.h
@@ -37,7 +37,9 @@ extern val long_s, ulong_s;
extern val double_s;
-extern val wstr_s;
+extern val str_d_s, wstr_s, wstr_d_s;
+
+extern val buf_d_s;
extern val ptr_in_s, ptr_out_s, ptr_in_out_s;