diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-07-09 17:21:16 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-07-09 17:21:16 -0700 |
commit | 3cba6501c6b20ca5da11b62da35a313bd557d094 (patch) | |
tree | ca61a7b6b1f718feedb456b96ccfad99a15cbd93 | |
parent | e7698eff01592fc39953836bbe896444587e7f8b (diff) | |
download | txr-3cba6501c6b20ca5da11b62da35a313bd557d094.tar.gz txr-3cba6501c6b20ca5da11b62da35a313bd557d094.tar.bz2 txr-3cba6501c6b20ca5da11b62da35a313bd557d094.zip |
ffi: new function, zero-fill.
* ffi.c (zero_fill): New function.
(ffi_init): zero-fill intrinsic registered.
* ffi.h (zero_fill): Declared.
* txr.1: Documented.
-rw-r--r-- | ffi.c | 33 | ||||
-rw-r--r-- | ffi.h | 1 | ||||
-rw-r--r-- | txr.1 | 34 |
3 files changed, 67 insertions, 1 deletions
@@ -5406,6 +5406,38 @@ val make_zstruct(val type, struct args *args) return strct; } +val zero_fill(val type, val obj) +{ + val self = lit("zero-fill"); + struct txr_ffi_type *tft = ffi_type_struct_checked(type); + cnum size = tft->size; + int need_free = (size >= 1024); + mem_t *buf = if3(need_free, chk_calloc(1, size), coerce(mem_t *, zalloca(size))); + val ret = nil; + + if (need_free) { + uw_simple_catch_begin; + + if (tft->in != 0) + ret = tft->in(tft, 1, buf, obj, self); + else + ret = tft->get(tft, buf, self); + + uw_unwind { + free(buf); + } + + uw_catch_end; + } else { + if (tft->in != 0) + ret = tft->in(tft, 1, buf, obj, self); + else + ret = tft->get(tft, buf, self); + } + + return ret; +} + void ffi_init(void) { prot1(&ffi_typedef_hash); @@ -5533,6 +5565,7 @@ void ffi_init(void) reg_fun(intern(lit("union-in"), user_package), func_n3(union_in)); reg_fun(intern(lit("union-out"), user_package), func_n3(union_out)); reg_fun(intern(lit("make-zstruct"), user_package), func_n1v(make_zstruct)); + reg_fun(intern(lit("zero-fill"), user_package), func_n2(zero_fill)); ffi_typedef_hash = make_hash(nil, nil, nil); ffi_init_types(); ffi_init_extra_types(); @@ -131,4 +131,5 @@ val union_put(val uni, val memb, val newval); val union_in(val uni, val memb, val memb_obj); val union_out(val uni, val memb, val memb_obj); val make_zstruct(val type, struct args *args); +val zero_fill(val type, val obj); void ffi_init(void); @@ -57082,7 +57082,14 @@ following equivalence holds: (ffi expr) <--> (ffi-type-compile 'expr) .cble -.SS* Zero-filled Struct Initialization +.SS* Zero-filled Object Support + +Communicating with foreign interfaces sometimes requires representations +to be initialized consisting of all zero bits, or mostly zero bits. + +\*(TX provides convenient ways to prepare Lisp objects such that when those +objects are converted to a foreign representation, they generate zero-filled +representations. .coNP Function @ make-zstruct .synb @@ -57206,6 +57213,31 @@ the following results are observed: (znew foo b 42) -> #S(foo a #<cptr bar: 0> b 42 c nil) .cble +.coNP Function @ zero-fill +.synb +.mets (zero-fill < type << obj ) +.syne +.desc +The +.code zero-fill +function invokes the by-reference in semantics of FFI type +.meta type +against a zero-filled buffer, and a Lisp object +.metn obj . + +This means that if +.meta obj +is an aggregate such as a vector, list or structure, +it is updated as if from an all-zero-bit foreign representation. +In that situation, +.meta obj +is also returned. + +An object which has by-value semantics, such as an integer, +is not updated. In this case, nevertheless, the return value +is a Lisp object produced by converting an all-zero-bit buffer to +.metn type . + .SS* Foreign Unions The following group of functions provides the means for working |