[pypy-svn] r46746 - pypy/dist/pypy/rpython/lltypesystem
arigo at codespeak.net
arigo at codespeak.net
Wed Sep 19 21:20:27 CEST 2007
Author: arigo
Date: Wed Sep 19 21:20:25 2007
New Revision: 46746
Modified:
pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
Log:
Stop using the deprecated ctypes.SetPointerType().
The new way to make recursive structures in ctypes is
to set the _fields_ attribute later. This is a bit
delicate but overall it looks like a clean-up.
Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Wed Sep 19 21:20:25 2007
@@ -21,8 +21,6 @@
_ctypes_cache = {}
-_delayed_ptrs = []
-_gettype_recursion = 0
def _setup_ctypes_cache():
from pypy.rpython.lltypesystem import rffi
@@ -44,18 +42,22 @@
rffi.SIZE_T: ctypes.c_size_t,
})
-def build_ctypes_struct(S, max_n=None):
- fields = []
- for fieldname in S._names:
- FIELDTYPE = S._flds[fieldname]
- if max_n is not None and fieldname == S._arrayfld:
- cls = build_ctypes_array(FIELDTYPE, max_n)
- else:
- cls = get_ctypes_type(FIELDTYPE)
- fields.append((fieldname, cls))
+def build_ctypes_struct(S, delayed_builders, max_n=None):
+ def builder():
+ # called a bit later to fill in _fields_
+ # (to handle recursive structure pointers)
+ fields = []
+ for fieldname in S._names:
+ FIELDTYPE = S._flds[fieldname]
+ if max_n is not None and fieldname == S._arrayfld:
+ cls = build_ctypes_array(FIELDTYPE, None, max_n)
+ else:
+ cls = get_ctypes_type(FIELDTYPE)
+ fields.append((fieldname, cls))
+ CStruct._fields_ = fields
class CStruct(ctypes.Structure):
- _fields_ = fields
+ # no _fields_: filled later by builder()
def _malloc(cls, n=None):
if S._arrayfld is None:
@@ -66,7 +68,7 @@
else:
if n is None:
raise TypeError("%r is variable-sized" % (S,))
- biggercls = build_ctypes_struct(S, n)
+ biggercls = build_ctypes_struct(S, None, n)
bigstruct = biggercls()
array = getattr(bigstruct, S._arrayfld)
if hasattr(array, 'length'):
@@ -77,12 +79,15 @@
CStruct.__name__ = 'ctypes_%s' % (S,)
if max_n is not None:
CStruct._normalized_ctype = get_ctypes_type(S)
+ builder() # no need to be lazy here
+ else:
+ delayed_builders.append(builder)
return CStruct
-def build_ctypes_array(A, max_n=0):
+def build_ctypes_array(A, delayed_builders, max_n=0):
assert max_n >= 0
ITEM = A.OF
- ctypes_item = get_ctypes_type(ITEM)
+ ctypes_item = get_ctypes_type(ITEM, delayed_builders)
class CArray(ctypes.Structure):
if not A._hints.get('nolength'):
@@ -94,7 +99,7 @@
def _malloc(cls, n=None):
if not isinstance(n, int):
raise TypeError, "array length must be an int"
- biggercls = build_ctypes_array(A, n)
+ biggercls = build_ctypes_array(A, None, n)
bigarray = biggercls()
if hasattr(bigarray, 'length'):
bigarray.length = n
@@ -127,27 +132,24 @@
CArray._normalized_ctype = get_ctypes_type(A)
return CArray
-def get_ctypes_type(T):
+def get_ctypes_type(T, delayed_builders=None):
try:
return _ctypes_cache[T]
except KeyError:
- global _gettype_recursion
- _gettype_recursion += 1
- try:
- cls = build_new_ctypes_type(T)
- if T not in _ctypes_cache:
- _ctypes_cache[T] = cls
- else:
- # check for buggy recursive structure logic
- assert _ctypes_cache[T] is cls
-
- if _gettype_recursion == 1:
- complete_pointer_types()
- finally:
- _gettype_recursion -= 1
+ toplevel = delayed_builders is None
+ if toplevel:
+ delayed_builders = []
+ cls = build_new_ctypes_type(T, delayed_builders)
+ if T not in _ctypes_cache:
+ _ctypes_cache[T] = cls
+ else:
+ # check for buggy recursive structure logic
+ assert _ctypes_cache[T] is cls
+ if toplevel:
+ complete_builders(delayed_builders)
return cls
-def build_new_ctypes_type(T):
+def build_new_ctypes_type(T, delayed_builders):
if isinstance(T, lltype.Ptr):
if isinstance(T.TO, lltype.FuncType):
argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS]
@@ -156,18 +158,12 @@
else:
restype = get_ctypes_type(T.TO.RESULT)
return ctypes.CFUNCTYPE(restype, *argtypes)
- elif isinstance(T.TO, lltype.Struct):
- # for recursive structures: build a forward pointer first
- uniquename = 'ctypes_%s_%d' % (T.TO.__name__, len(_ctypes_cache))
- pcls = ctypes.POINTER(uniquename)
- _delayed_ptrs.append((pcls, T.TO))
- return pcls
else:
- return ctypes.POINTER(get_ctypes_type(T.TO))
+ return ctypes.POINTER(get_ctypes_type(T.TO, delayed_builders))
elif isinstance(T, lltype.Struct):
- return build_ctypes_struct(T)
+ return build_ctypes_struct(T, delayed_builders)
elif isinstance(T, lltype.Array):
- return build_ctypes_array(T)
+ return build_ctypes_array(T, delayed_builders)
elif isinstance(T, lltype.OpaqueType):
if T.hints.get('external', None) != 'C':
raise TypeError("%s is not external" % T)
@@ -178,10 +174,9 @@
return _ctypes_cache[T]
raise NotImplementedError(T)
-def complete_pointer_types():
- while _delayed_ptrs:
- pcls, S = _delayed_ptrs.pop()
- ctypes.SetPointerType(pcls, get_ctypes_type(S))
+def complete_builders(delayed_builders):
+ while delayed_builders:
+ delayed_builders.pop()()
def convert_struct(container, cstruct=None):
More information about the Pypy-commit
mailing list