def prep_string(s): """Takes a Pixie string and returns a VoidP to that string. The string should be freed via dispose!, otherwise memory leaks could result.""" affirm(isinstance(s, String), u"Can only prep strings with prep-string") utf8 = unicode_to_utf8(rt.name(s)) raw = rffi.str2charp(utf8) return VoidP(rffi.cast(rffi.VOIDP, raw))
def unpack(ptr, offset, tp): """(unpack ptr offset tp) Reads a value of type tp from offset of ptr.""" affirm(isinstance(ptr, VoidP) or isinstance(ptr, Buffer) or isinstance(ptr, CStruct), u"Type is not unpackable") affirm(isinstance(tp, CType), u"Packing type must be a CType") ptr = rffi.ptradd(ptr.raw_data(), offset.int_val()) return tp.ffi_get_value(ptr)
def ffi_prep_callback(tp, f): """(ffi-prep-callback callback-tp fn) Prepares a Pixie function for use as a c callback. callback-tp is a ffi callback type, fn is a pixie function (can be a closure, native fn or any object that implements -invoke. Returns a function pointer that can be passed to c and invoked as a callback.""" affirm(isinstance(tp, CFunctionType), u"First argument to ffi-prep-callback must be a CFunctionType") raw_closure = rffi.cast(rffi.VOIDP, clibffi.closureHeap.alloc()) if not we_are_translated(): unique_id = id_generator.get_next() else: unique_id = rffi.cast(lltype.Signed, raw_closure) res = clibffi.c_ffi_prep_closure( rffi.cast(clibffi.FFI_CLOSUREP, raw_closure), tp.get_cd().cif, invoke_callback, rffi.cast(rffi.VOIDP, unique_id)) if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK: registered_callbacks[unique_id] = None runtime_error(u"libffi failed to build this callback") cb = CCallback(tp, raw_closure, unique_id, f) registered_callbacks[unique_id] = cb return cb
def ffi_prep_callback(tp, f): """(ffi-prep-callback callback-tp fn) Prepares a Pixie function for use as a c callback. callback-tp is a ffi callback type, fn is a pixie function (can be a closure, native fn or any object that implements -invoke. Returns a function pointer that can be passed to c and invoked as a callback.""" affirm(isinstance(tp, CFunctionType), u"First argument to ffi-prep-callback must be a CFunctionType") raw_closure = rffi.cast(rffi.VOIDP, clibffi.closureHeap.alloc()) if not we_are_translated(): unique_id = id_generator.get_next() else: unique_id = rffi.cast(lltype.Signed, raw_closure) res = clibffi.c_ffi_prep_closure(rffi.cast(clibffi.FFI_CLOSUREP, raw_closure), tp.get_cd().cif, invoke_callback, rffi.cast(rffi.VOIDP, unique_id)) if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK: registered_callbacks[unique_id] = None runtime_error(u"libffi failed to build this callback") cb = CCallback(tp, raw_closure, unique_id, f) registered_callbacks[unique_id] = cb return cb
def ffi_set_value(self, ptr, val): affirm(isinstance(val, CCallback), u"Can only encode CCallbacks as function pointers") casted = rffi.cast(rffi.VOIDPP, ptr) casted[0] = val.get_raw_closure() return None
def pack(ptr, offset, tp, val): """(pack! ptr offset tp val) Writes val at offset of ptr with the format tp""" affirm(isinstance(ptr, VoidP) or isinstance(ptr, Buffer) or isinstance(ptr, CStruct), u"Type is not unpackable") affirm(isinstance(tp, CType), u"Packing type must be a CType") ptr = rffi.ptradd(ptr.raw_data(), offset.int_val()) tp.ffi_set_value(ptr, val) return nil
def ffi_set_value(self, ptr, val): pnt = rffi.cast(rffi.VOIDPP, ptr) if isinstance(val, Buffer): pnt[0] = val.buffer() elif isinstance(val, VoidP): pnt[0] = val.raw_data() else: print val affirm(False, u"Cannot encode this type")
def ffi_set_value(self, ptr, val): if isinstance(val, CCallback): casted = rffi.cast(rffi.VOIDPP, ptr) casted[0] = val.get_raw_closure() elif val is nil: casted = rffi.cast(rffi.VOIDPP, ptr) casted[0] = rffi.cast(rffi.VOIDP, 0) else: frm_name = rt.name(rt.str(val.type())) to_name = rt.name(rt.str(self)) affirm(False, u"Cannot encode " + frm_name + u" as " + to_name) return None
def c_struct(name, size, spec): d = {} for x in range(rt.count(spec)): row = rt.nth(spec, rt.wrap(x)) nm = rt.nth(row, rt.wrap(0)) tp = rt.nth(row, rt.wrap(1)) offset = rt.nth(row, rt.wrap(2)) affirm(isinstance(nm, Keyword), u"c-struct field names must be keywords") if not isinstance(tp, CType): runtime_error(u"c-struct field types must be c types, got: " + rt.name(rt.str(tp))) d[nm] = (tp, offset.int_val()) return CStructType(rt.name(name), size.int_val(), d)
def c_struct(name, size, spec): """(c-struct name size spec) Creates a CStruct named name, of size size, with the given spec. Spec is a vector of vectors. Each row of the format [field-name type offset]""" d = {} for x in range(rt.count(spec)): row = rt.nth(spec, rt.wrap(x)) nm = rt.nth(row, rt.wrap(0)) tp = rt.nth(row, rt.wrap(1)) offset = rt.nth(row, rt.wrap(2)) affirm(isinstance(nm, Keyword), u"c-struct field names must be keywords") #if not isinstance(tp, CType): # runtime_error(u"c-struct field types must be c types, got: " + rt.name(rt.str(tp))) d[nm] = (tp, offset.int_val()) tp = CStructType(rt.name(name), size.int_val(), d) proto._dispose_BANG_.extend(tp, _dispose_cstruct) return tp
def ffi_set_value(self, ptr, val): pnt = rffi.cast(rffi.VOIDPP, ptr) if isinstance(val, String): pnt = rffi.cast(rffi.CCHARPP, ptr) utf8 = unicode_to_utf8(rt.name(val)) raw = rffi.str2charp(utf8) pnt[0] = raw return CCharPToken(raw) elif isinstance(val, Buffer): pnt[0] = val.buffer() elif isinstance(val, VoidP): pnt[0] = val.raw_data() elif val is nil: pnt[0] = rffi.cast(rffi.VOIDP, 0) elif isinstance(val, CStruct): pnt[0] = rffi.cast(rffi.VOIDP, val.raw_data()) else: frm_name = rt.name(rt.str(val.type())) to_name = rt.name(rt.str(self)) affirm(False, u"Cannot encode " + frm_name + u" as " + to_name)
def _ffi_fn(lib, nm, args, ret_type): affirm(isinstance(lib, ExternalLib), u"First argument must be an ExternalLib") affirm(isinstance(ret_type, object.Type), u"Ret type must be a type") affirm(rt.namespace(nm) is None, u"Name must not be namespaced") cnt = rt.count(args) new_args = [None] * cnt for x in range(cnt): t = rt.nth(args, rt.wrap(x)) affirm(isinstance(t, object.Type), u"Arg defs must be types") new_args[x] = t f = FFIFn(lib, rt.name(nm), new_args, ret_type) return f
def ffi_set_value(self, ptr, val): if isinstance(val, String): pnt = rffi.cast(rffi.CCHARPP, ptr) utf8 = unicode_to_utf8(rt.name(val)) raw = rffi.str2charp(utf8) pnt[0] = raw return CCharPToken(raw) elif isinstance(val, Buffer): vpnt = rffi.cast(rffi.VOIDPP, ptr) vpnt[0] = val.buffer() elif isinstance(val, VoidP): vpnt = rffi.cast(rffi.VOIDPP, ptr) vpnt[0] = val.raw_data() elif val is nil: vpnt = rffi.cast(rffi.VOIDPP, ptr) vpnt[0] = rffi.cast(rffi.VOIDP, 0) elif isinstance(val, CStruct): vpnt = rffi.cast(rffi.VOIDPP, ptr) vpnt[0] = rffi.cast(rffi.VOIDP, val.raw_data()) else: print val affirm(False, u"Cannot encode this type")
def pack(ptr, offset): affirm(isinstance(ptr, VoidP) or isinstance(ptr, Buffer) or isinstance(ptr, CStruct), u"Type is not unpackable") ptr = rffi.ptradd(ptr.raw_data(), offset.int_val()) return VoidP(ptr)
def _ffi_voidp(lib, nm): affirm(isinstance(lib, ExternalLib), u"First argument to ffi-voidp should be an external library") name = rt.name(nm) return VoidP(lib.get_fn_ptr(name))
def _ffi_fn__args(args): affirm(len(args) >= 4, u"ffi-fn requires at least 4 arguments") lib, nm, arg_types, ret_type = args[:4] affirm(isinstance(lib, ExternalLib), u"First argument must be an ExternalLib") affirm(isinstance(ret_type, object.Type), u"Ret type must be a type") affirm(rt.namespace(nm) is None, u"Name must not be namespaced") cnt = rt.count(arg_types) new_args = [None] * cnt for x in range(cnt): t = rt.nth(arg_types, rt.wrap(x)) affirm(isinstance(t, object.Type), u"Arg defs must be types") new_args[x] = t kwargs = args[4:] affirm(len(kwargs) & 0x1 == 0, u"ffi-fn requires even number of options") is_variadic = False for i in range(0, len(kwargs)/2, 2): key = kwargs[i] val = kwargs[i+1] affirm(isinstance(key, Keyword), u"ffi-fn options should be keyword/bool pairs") affirm(val is true or val is false, u"ffi-fn options should be keyword/bool pairs") k = rt.name(key) if k == u"variadic?": is_variadic = True if val is true else False else: affirm(False, u"unknown ffi-fn option: :" + k) tp = CFunctionType(new_args, ret_type, is_variadic) nm = rt.name(nm) f = FFIFn(nm, lib.get_fn_ptr(nm), tp) return f
def prep_ffi_call__args(args): fn = args[0] affirm(isinstance(fn, CFunctionType), u"First arg must be a FFI function")
def _ffi_fn__args(args): affirm(len(args) >= 4, u"ffi-fn requires at least 4 arguments") lib, nm, arg_types, ret_type = args[:4] affirm(isinstance(lib, ExternalLib), u"First argument must be an ExternalLib") affirm(isinstance(ret_type, object.Type), u"Ret type must be a type") affirm(rt.namespace(nm) is None, u"Name must not be namespaced") cnt = rt.count(arg_types) new_args = [None] * cnt for x in range(cnt): t = rt.nth(arg_types, rt.wrap(x)) affirm(isinstance(t, object.Type), u"Arg defs must be types") new_args[x] = t kwargs = args[4:] affirm(len(kwargs) & 0x1 == 0, u"ffi-fn requires even number of options") is_variadic = False for i in range(0, len(kwargs) / 2, 2): key = kwargs[i] val = kwargs[i + 1] affirm(isinstance(key, Keyword), u"ffi-fn options should be keyword/bool pairs") affirm(val is true or val is false, u"ffi-fn options should be keyword/bool pairs") k = rt.name(key) if k == u"variadic?": is_variadic = True if val is true else False else: affirm(False, u"unknown ffi-fn option: :" + k) tp = CFunctionType(new_args, ret_type, is_variadic) nm = rt.name(nm) f = FFIFn(nm, lib.get_fn_ptr(nm), tp) return f
def pack(ptr, offset): affirm( isinstance(ptr, VoidP) or isinstance(ptr, Buffer) or isinstance(ptr, CStruct), u"Type is not unpackable") ptr = rffi.ptradd(ptr.raw_data(), offset.int_val()) return VoidP(ptr)