[pypy-commit] pypy cffi-1.0: ffi.new_handle(), ffi.from_handle()
arigo
noreply at buildbot.pypy.org
Sun May 3 11:16:43 CEST 2015
Author: Armin Rigo <arigo at 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)
+ at jit.elidable
@unwrap_spec(name=str)
def new_primitive_type(space, name):
unique_cache = space.fromcache(UniqueCache)
@@ -154,6 +157,7 @@
# ____________________________________________________________
+ at 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 @@
# ____________________________________________________________
+ at 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)
+ at jit.elidable
def _new_array_type(space, w_ctptr, length):
unique_cache = space.fromcache(UniqueCache)
unique_key = (w_ctptr, length)
@@ -493,12 +499,20 @@
# ____________________________________________________________
+ at 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
+ at 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 @@
# ____________________________________________________________
+ at 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))
+ at 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:
More information about the pypy-commit
mailing list