Author: Armin Rigo <ar...@tunes.org> Branch: cffi-1.0 Changeset: r77000:b7ff7697276d Date: 2015-05-03 11:16 +0200 http://bitbucket.org/pypy/pypy/changeset/b7ff7697276d/
Log: ffi.new_handle(), ffi.from_handle() diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py --- a/pypy/module/_cffi_backend/ffi_obj.py +++ b/pypy/module/_cffi_backend/ffi_obj.py @@ -7,7 +7,7 @@ from pypy.module._cffi_backend import parse_c_type, realize_c_type from pypy.module._cffi_backend import newtype, cerrno, ccallback, ctypearray -from pypy.module._cffi_backend import ctypestruct, ctypeptr +from pypy.module._cffi_backend import ctypestruct, ctypeptr, handle from pypy.module._cffi_backend.ctypeobj import W_CType from pypy.module._cffi_backend.cdataobj import W_CData @@ -154,6 +154,17 @@ _cffi_backend.callback(ctype, python_callable, error))""") + @unwrap_spec(w_arg=W_CData) + def descr_from_handle(self, w_arg): + """\ +Cast a 'void *' back to a Python object. Must be used *only* on the +pointers returned by new_handle(), and *only* as long as the exact +cdata object returned by new_handle() is still alive (somewhere else +in the program). Failure to follow these rules will crash.""" + # + return handle.from_handle(self.space, w_arg) + + @unwrap_spec(replace_with=str) def descr_getctype(self, w_cdecl, replace_with=''): """\ @@ -211,6 +222,17 @@ return w_ctype.newp(w_init) + def descr_new_handle(self, w_arg): + """\ +Return a non-NULL cdata of type 'void *' that contains an opaque +reference to the argument, which can be any Python object. To cast it +back to the original object, use from_handle(). You must keep alive +the cdata object returned by new_handle()!""" + # + space = self.space + return handle._newp_handle(space, newtype.new_voidp_type(space), w_arg) + + @unwrap_spec(w_cdata=W_CData, maxlen=int) def descr_string(self, w_cdata, maxlen=-1): """\ @@ -273,15 +295,17 @@ addressof = interp2app(W_FFIObject.descr_addressof), alignof = interp2app(W_FFIObject.descr_alignof), callback = interp2app(W_FFIObject.descr_callback), + from_handle = interp2app(W_FFIObject.descr_from_handle), getctype = interp2app(W_FFIObject.descr_getctype), new = interp2app(W_FFIObject.descr_new), + new_handle = interp2app(W_FFIObject.descr_new_handle), sizeof = interp2app(W_FFIObject.descr_sizeof), string = interp2app(W_FFIObject.descr_string), typeof = interp2app(W_FFIObject.descr_typeof), ) def _startup(space): - ctvoidp = newtype.new_pointer_type(space, newtype.new_void_type(space)) + ctvoidp = newtype.new_voidp_type(space) w_NULL = ctvoidp.cast(space.wrap(0)) w_ffitype = space.gettypefor(W_FFIObject) w_ffitype.dict_w['NULL'] = w_NULL diff --git a/pypy/module/_cffi_backend/handle.py b/pypy/module/_cffi_backend/handle.py --- a/pypy/module/_cffi_backend/handle.py +++ b/pypy/module/_cffi_backend/handle.py @@ -14,17 +14,20 @@ # ____________________________________________________________ +def _newp_handle(space, w_ctype, w_x): + index = get(space).reserve_next_handle_index() + _cdata = rffi.cast(rffi.CCHARP, index + 1) + new_cdataobj = cdataobj.W_CDataHandle(space, _cdata, w_ctype, w_x) + get(space).store_handle(index, new_cdataobj) + return new_cdataobj + @unwrap_spec(w_ctype=ctypeobj.W_CType) def newp_handle(space, w_ctype, w_x): if (not isinstance(w_ctype, ctypeptr.W_CTypePointer) or not w_ctype.is_void_ptr): raise oefmt(space.w_TypeError, "needs 'void *', got '%s'", w_ctype.name) - index = get(space).reserve_next_handle_index() - _cdata = rffi.cast(rffi.CCHARP, index + 1) - new_cdataobj = cdataobj.W_CDataHandle(space, _cdata, w_ctype, w_x) - get(space).store_handle(index, new_cdataobj) - return new_cdataobj + return _newp_handle(space, w_ctype, w_x) @unwrap_spec(w_cdata=cdataobj.W_CData) def from_handle(space, w_cdata): diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py --- a/pypy/module/_cffi_backend/newtype.py +++ b/pypy/module/_cffi_backend/newtype.py @@ -4,6 +4,7 @@ from rpython.rlib.objectmodel import specialize, r_dict, compute_identity_hash from rpython.rlib.rarithmetic import ovfcheck, intmask +from rpython.rlib import jit from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.tool import rffi_platform @@ -23,6 +24,7 @@ class UniqueCache: def __init__(self, space): self.ctvoid = None # There can be only one + self.ctvoidp = None # Cache for self.pointers[self.ctvoid] self.primitives = {} # Keys: name self.pointers = {} # Keys: base_ctype self.arrays = {} # Keys: (ptr_ctype, length_or_-1) @@ -137,6 +139,7 @@ eptypesize("int_fast64_t", 8, _WCTSigned) eptypesize("uint_fast64_t", 8, _WCTUnsign) +@jit.elidable @unwrap_spec(name=str) def new_primitive_type(space, name): unique_cache = space.fromcache(UniqueCache) @@ -154,6 +157,7 @@ # ____________________________________________________________ +@jit.elidable @unwrap_spec(w_ctype=ctypeobj.W_CType) def new_pointer_type(space, w_ctype): unique_cache = space.fromcache(UniqueCache) @@ -167,6 +171,7 @@ # ____________________________________________________________ +@jit.elidable @unwrap_spec(w_ctptr=ctypeobj.W_CType) def new_array_type(space, w_ctptr, w_length): if space.is_w(w_length, space.w_None): @@ -178,6 +183,7 @@ space.wrap("negative array length")) return _new_array_type(space, w_ctptr, length) +@jit.elidable def _new_array_type(space, w_ctptr, length): unique_cache = space.fromcache(UniqueCache) unique_key = (w_ctptr, length) @@ -493,12 +499,20 @@ # ____________________________________________________________ +@jit.elidable def new_void_type(space): unique_cache = space.fromcache(UniqueCache) if unique_cache.ctvoid is None: unique_cache.ctvoid = ctypevoid.W_CTypeVoid(space) return unique_cache.ctvoid +@jit.elidable +def new_voidp_type(space): + unique_cache = space.fromcache(UniqueCache) + if unique_cache.ctvoidp is None: + unique_cache.ctvoidp = new_pointer_type(space, new_void_type(space)) + return unique_cache.ctvoidp + # ____________________________________________________________ @unwrap_spec(name=str, w_basectype=ctypeobj.W_CType) @@ -537,6 +551,7 @@ # ____________________________________________________________ +@jit.elidable @unwrap_spec(w_fresult=ctypeobj.W_CType, ellipsis=int) def new_function_type(space, w_fargs, w_fresult, ellipsis=0): fargs = [] @@ -549,6 +564,7 @@ fargs.append(w_farg) return _new_function_type(space, fargs, w_fresult, bool(ellipsis)) +@jit.elidable def _new_function_type(space, fargs, w_fresult, ellipsis=False): from pypy.module._cffi_backend import ctypefunc # diff --git a/pypy/module/_cffi_backend/realize_c_type.py b/pypy/module/_cffi_backend/realize_c_type.py --- a/pypy/module/_cffi_backend/realize_c_type.py +++ b/pypy/module/_cffi_backend/realize_c_type.py @@ -71,7 +71,7 @@ w_ctype = realize_cache.all_primitives[num] if w_ctype is None: if num == cffi_opcode.PRIM_VOID: - w_ctype = newtype.new_void_type() + w_ctype = newtype.new_void_type(space) elif 0 <= num < len(RealizeCache.NAMES) and RealizeCache.NAMES[num]: w_ctype = newtype.new_primitive_type(space, RealizeCache.NAMES[num]) else: _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit