diff options
-rw-r--r-- | ffi.c | 35 | ||||
-rw-r--r-- | txr.1 | 131 |
2 files changed, 166 insertions, 0 deletions
@@ -3670,6 +3670,15 @@ static val ffi_type_lookup(val sym) return gethash(ffi_typedef_hash, sym); } +static val ffi_type_lookup_checked(val self, val sym) +{ + val type = gethash(ffi_typedef_hash, sym); + if (!type) + uw_throwf(error_s, lit("~a: unrecognized type specifier: ~s"), + self, sym, nao); + return type; +} + static val ffi_struct_init(val slot_init, val strct) { val stype = struct_type(strct); @@ -5947,6 +5956,30 @@ val fill_carray(val carray, val offs, val stream) return ret; } +static val cptr_getobj(val cptr, val type_in) +{ + val self = lit("cptr-get"); + mem_t *data = cptr_get(cptr); + val type = default_arg(type_in, ffi_type_lookup_checked(self, cptr->co.cls)); + struct txr_ffi_type *tft = ffi_type_struct_checked(self, type); + if (data != 0) + return tft->get(tft, data, self); + uw_throwf(type_error_s, lit("~a: ~s is a null pointer"), self, cptr, nao); +} + +static val cptr_out(val cptr, val obj, val type_in) +{ + val self = lit("cptr-out"); + mem_t *data = cptr_get(cptr); + val type = default_arg(type_in, ffi_type_lookup_checked(self, cptr->co.cls)); + struct txr_ffi_type *tft = ffi_type_struct_checked(self, type); + if (data != 0) { + tft->out(tft, 0, obj, data, self); + return obj; + } + uw_throwf(type_error_s, lit("~a: ~s is a null pointer"), self, cptr, nao); +} + struct uni { struct txr_ffi_type *tft; mem_t *data; @@ -6345,6 +6378,8 @@ void ffi_init(void) } reg_fun(intern(lit("put-carray"), user_package), func_n3o(put_carray, 1)); reg_fun(intern(lit("fill-carray"), user_package), func_n3o(fill_carray, 1)); + reg_fun(intern(lit("cptr-get"), user_package), func_n2o(cptr_getobj, 1)); + reg_fun(intern(lit("cptr-out"), user_package), func_n3o(cptr_out, 2)); reg_fun(intern(lit("make-union"), user_package), func_n3o(make_union, 1)); reg_fun(intern(lit("union-members"), user_package), func_n1(union_members)); reg_fun(intern(lit("union-get"), user_package), func_n2(union_get)); @@ -53452,6 +53452,137 @@ function retrieves the .meta cptr object's type tag. +.coNP Function @ cptr-get +.synb +.mets (cptr-get < cptr <> [ type ]) +.syne +.desc +The +.code cptr-get +function extracts a Lisp value by converting a C object +at the memory location denoted by +.metn cptr , +according to the FFI type +.metn type . +The external representation at the specified memory location is +is scanned according to the +.meta type +and converted to a Lisp value which is returned. + +If the +.meta type +argument is specified, it must be a FFI type object. +If omitted, then the +.code cptr +object's type tag is interpreted as a FFI type symbol and resolved to +a type; the resulting type, if one is found is substituted for +.metn type . +If the lookup fails an error exception is thrown. + +The +.meta cptr +object must be of type +.code cptr +and point to a memory area suitably aligned for, and large +enough to hold a foreign representation of +.metn type , +at the byte offset indicated by the +.meta offset +argument. + +If +.meta cptr +is a null pointer, an exception is thrown. + +The +.code cptr-get +operation is similar to the "get semantics" performed by FFI +in order to extract the return value of foreign function +calls, and by the FFI callback mechanism to extract the +arguments coming into a callback. + +The +.meta type +argument may not be a variable length type, such as an array of +unspecified size. + +Note: the +.code cptr-get +and +.code cptr-out +is useful in simplifying the interaction with "semi-opaque" foreign objects: +objects which serve as a API handles that are treated as opaque pointers in API +argument calls, but which expose some internal members that the application +must access directly. The +.code cptr +objects pass through the foreign API without undergoing conversion, +as usual. The application uses these two functions to perform conversion as +necessary. Under this technique, the description of the foreign object need not +be complete. Structure members which occur after the last member that the +application is interested in need not be described in the FFI type. + +.coNP Function @ cptr-put +.synb +.mets (cptr-put < cptr < obj <> [ type ]) +.syne +.desc +The +.code cptr-put +function converts a Lisp value into a C representation, +which is stored at the memory location denoted by +.metn cptr , +according to the FFI type +.metn type . +The function's return value is +.metn obj . + +If the +.meta type +argument is specified, it must be a FFI type object. +If omitted, then the +.code cptr +object's type tag is interpreted as a FFI type symbol and resolved to +a type; the resulting type, if one is found is substituted for +.metn type . +If the lookup fails an error exception is thrown. + +The +.meta obj +argument must be an object compatible with the conversions +implied by +.metn type . + +The +.meta cptr +object must be of type +.code cptr +and point to a memory area suitably aligned for, and large +enough to hold a foreign representation of +.metn type , +at the byte offset indicated by the +.meta offset +argument. + +If +.meta cptr +is a null pointer, an exception is thrown. + +It is assumed that +.meta obj +is an object which was returned by an earlier call to +.codn cptr-get , +and that the +.meta cptr +and +.meta type +arguments are the same objects that were used in that call. + +The +.code cptr-out +function performs the "out semantics" encoding action, similar +to the treatment applied to the arguments of a callback prior to +returning to foreign code. + .coNP Variable @ cptr-null .desc The |