[pypy-svn] r45029 - in pypy/dist/pypy/rpython/lltypesystem: . test
arigo at codespeak.net
arigo at codespeak.net
Fri Jul 13 17:09:26 CEST 2007
Author: arigo
Date: Fri Jul 13 17:09:25 2007
New Revision: 45029
Added:
pypy/dist/pypy/rpython/lltypesystem/lltype2ctypes.py (contents, props changed)
pypy/dist/pypy/rpython/lltypesystem/test/test_lltype2ctypes.py (contents, props changed)
Modified:
pypy/dist/pypy/rpython/lltypesystem/lltype.py
Log:
(lac, arigo, pedronis around)
Another approach: can convert _struct in-place to internally use a
ctypes.Structure.
Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Fri Jul 13 17:09:25 2007
@@ -1191,16 +1191,19 @@
'_parent_type', '_parent_index', '_keepparent',
'_wrparent',
'__weakref__',
- '_dead')
+ '_dead',
+ '_ctypes_storage')
def __init__(self, TYPE):
self._wrparent = None
self._TYPE = TYPE
self._dead = False
+ self._ctypes_storage = None
def _free(self):
self._check() # no double-frees
self._dead = True
+ self._ctypes_storage = None
def _setparentstructure(self, parent, parentindex):
self._wrparent = weakref.ref(parent)
@@ -1317,7 +1320,18 @@
if isinstance(r, _uninitialized) and not uninitialized_ok:
raise UninitializedMemoryAccess("%r.%s"%(self, field_name))
return r
-
+
+ def __getattr__(self, field_name):
+ if self._ctypes_storage is not None:
+ return self._ctypes_storage._getattr(field_name)
+ raise AttributeError(field_name)
+
+ def __setattr__(self, field_name, value):
+ if field_name.startswith('_') or self._ctypes_storage is None:
+ _parentable.__setattr__(self, field_name, value)
+ else:
+ self._ctypes_storage._setattr(field_name, value)
+
# for FixedSizeArray kind of structs:
def getlength(self):
Added: pypy/dist/pypy/rpython/lltypesystem/lltype2ctypes.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype2ctypes.py Fri Jul 13 17:09:25 2007
@@ -0,0 +1,108 @@
+import ctypes
+from pypy.rpython.lltypesystem import lltype
+
+
+_ctypes_cache = {
+ lltype.Signed: ctypes.c_long,
+ }
+
+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))
+
+ class CStruct(ctypes.Structure):
+ _fields_ = fields
+
+ def _malloc(cls, n=None):
+ if S._arrayfld is None:
+ if n is not None:
+ raise TypeError("%r is not variable-sized" % (S,))
+ storage = cls()
+ return storage
+ else:
+ if n is None:
+ raise TypeError("%r is variable-sized" % (S,))
+ biggercls = build_ctypes_struct(S, n)
+ bigstruct = biggercls()
+ getattr(bigstruct, S._arrayfld).length = n
+ return bigstruct
+ _malloc = classmethod(_malloc)
+
+ def _getattr(self, field_name):
+ cobj = getattr(self, field_name)
+ return ctypes2lltype(cobj)
+
+ def _setattr(self, field_name, value):
+ cobj = lltype2ctypes(value)
+ setattr(self, field_name, cobj)
+
+ CStruct.__name__ = 'ctypes_%s' % (S,)
+ return CStruct
+
+def build_ctypes_array(A, max_n=0):
+ assert max_n >= 0
+ ITEM = A.OF
+ ctypes_item = get_ctypes_type(ITEM)
+
+ class CArray(ctypes.Structure):
+ _fields_ = [('length', ctypes.c_int),
+ ('items', max_n * ctypes_item)]
+
+ def _malloc(cls, n=None):
+ if not isinstance(n, int):
+ raise TypeError, "array length must be an int"
+ biggercls = build_ctypes_array(A, n)
+ bigarray = biggercls()
+ bigarray.length = n
+ return bigarray
+ _malloc = classmethod(_malloc)
+
+ CArray.__name__ = 'ctypes_%s*%d' % (A, max_n)
+ return CArray
+
+def get_ctypes_type(T):
+ try:
+ return _ctypes_cache[T]
+ except KeyError:
+ if isinstance(T, lltype.Ptr):
+ cls = ctypes.POINTER(get_ctypes_type(T.TO))
+ elif isinstance(T, lltype.Struct):
+ cls = build_ctypes_struct(T)
+ elif isinstance(T, lltype.Array):
+ cls = build_ctypes_array(T)
+ else:
+ raise NotImplementedError(T)
+ _ctypes_cache[T] = cls
+ return cls
+
+
+def convert_struct(container):
+ STRUCT = container._TYPE
+ cls = get_ctypes_type(STRUCT)
+ cstruct = cls._malloc()
+ container._ctypes_storage = cstruct
+ for field_name in STRUCT._names:
+ field_value = getattr(container, field_name)
+ delattr(container, field_name)
+ setattr(cstruct, field_name, lltype2ctypes(field_value))
+
+def lltype2ctypes(llobj):
+ T = lltype.typeOf(llobj)
+ if isinstance(T, lltype.Ptr):
+ container = llobj._obj
+ if container._ctypes_storage is None:
+ if isinstance(T.TO, lltype.Struct):
+ convert_struct(container)
+ else:
+ raise NotImplementedError(T)
+ return ctypes.pointer(container._ctypes_storage)
+ return llobj
+
+def ctypes2lltype(cobj):
+ return cobj
Added: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype2ctypes.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype2ctypes.py Fri Jul 13 17:09:25 2007
@@ -0,0 +1,21 @@
+import ctypes
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem.lltype2ctypes import lltype2ctypes
+
+
+def test_primitive():
+ assert lltype2ctypes(5) == 5
+ assert lltype2ctypes('?') == '?'
+
+def test_simple_struct():
+ S = lltype.Struct('S', ('x', lltype.Signed))
+ s = lltype.malloc(S, flavor='raw')
+ s.x = 123
+ sc = lltype2ctypes(s)
+ assert isinstance(sc.contents, ctypes.Structure)
+ assert sc.contents.x == 123
+ sc.contents.x = 456
+ assert s.x == 456
+ s.x = 789
+ assert sc.contents.x == 789
+ lltype.free(s, flavor='raw')
More information about the Pypy-commit
mailing list