[pypy-svn] r50485 - pypy/branch/applevel-ctypes2/pypy/lib/_ctypes
fijal at codespeak.net
fijal at codespeak.net
Thu Jan 10 11:55:04 CET 2008
Author: fijal
Date: Thu Jan 10 11:55:04 2008
New Revision: 50485
Modified:
pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py
pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py
pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py
pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py
Log:
Wack enough to make 5 tests of test_pointers pass (no memory clearing yet,
it leaks like hell).
Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/__init__.py Thu Jan 10 11:55:04 2008
@@ -4,6 +4,7 @@
from _ctypes.dummy import _memmove_addr, _memset_addr, _string_at_addr
from _ctypes.dummy import _cast_addr
+from _ctypes.basics import _CData
from _ctypes.primitive import _SimpleCData, sizeof, alignment, byref
from _ctypes.pointer import _Pointer
from _ctypes.function import CFuncPtr
Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/function.py Thu Jan 10 11:55:04 2008
@@ -1,6 +1,7 @@
import _ffi
class CFuncPtrType(type):
+ # XXX write down here defaults and such things
pass
class CFuncPtr(object):
@@ -21,21 +22,43 @@
self.dll = None
def __call__(self, *args):
- assert self.argtypes is not None #XXX for now
- assert self.restype is not None #XXX for now
- if len(args) != len(self.argtypes):
- raise TypeError("%s takes %s arguments, given %s" % (self.name,
- len(self.argtypes), len(args)))
- return self._getfuncptr()(*args)
+ import ctypes
+ if self.restype is None:
+ # XXX point to default instead
+ self.restype = ctypes.c_int
+ if self.argtypes is not None:
+ if len(args) != len(self.argtypes):
+ raise TypeError("%s takes %s arguments, given %s" %
+ (self.name, len(self.argtypes), len(args)))
+ res = self._getfuncptr(args)(*[arg.value for arg in args])
+ if issubclass(self.restype, ctypes._SimpleCData):
+ return res
+ else:
+ # XXX pointers
+ return self.restype(address=res)
- def _getfuncptr(self):
+ def _getfuncptr(self, args):
if self._funcptr is not None:
if (self.argtypes is self._argtypes
and self.restype is self._restype):
return self._funcptr
- argtps = [argtype._type_ for argtype in self.argtypes]
- restp = self.restype._type_
+ if self.argtypes is None:
+ argtypes = self._guess_magic_args(args)
+ else:
+ argtypes = self.argtypes
+ argtps = [argtype._ffiletter for argtype in argtypes]
+ restp = self.restype._ffiletter
self._funcptr = funcptr = self.dll._handle.ptr(self.name, argtps, restp)
self._argtypes = self.argtypes
self._restype = self.restype
return funcptr
+
+ def _guess_magic_args(self, args):
+ import _ctypes
+ res = []
+ for arg in args:
+ if isinstance(arg, _ctypes._CData):
+ res.append(type(arg))
+ else:
+ raise TypeError("Cannot convert %s" % arg)
+ return res
Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/pointer.py Thu Jan 10 11:55:04 2008
@@ -1,30 +1,57 @@
import _ffi
+from _ctypes.basics import _CData
+
+DEFAULT_VALUE = object()
class PointerType(type):
def __new__(self, name, cls, typedict):
d = dict(
- size = _ffi.sizeof('P'),
- align = _ffi.alignment('P'),
- length = 1
+ size = _ffi.sizeof('P'),
+ align = _ffi.alignment('P'),
+ length = 1,
+ _ffiletter = 'P'
)
# XXX check if typedict['_type_'] is any sane
# XXX remember about paramfunc
obj = type.__new__(self, name, cls, typedict)
for k, v in d.iteritems():
setattr(obj, k, v)
+ if '_type_' in typedict:
+ ffiarray = _ffi.Array(typedict['_type_']._ffiletter)
+ def __init__(self, value=0, address=DEFAULT_VALUE):
+ if address is not DEFAULT_VALUE:
+ self._array = ffiarray.fromaddress(address, 1)
+ elif value == 0:
+ # null pointer
+ self._array = ffiarray.fromaddress(0, 1)
+ else:
+ self._array = ffiarray.fromaddress(value._array.buffer, 1)
+ obj._ffiarray = ffiarray
+ else:
+ def __init__(self, value=0):
+ raise TypeError("%s has no type" % obj)
+ obj.__init__ = __init__
return obj
-class _Pointer(object):
+class _Pointer(_CData):
__metaclass__ = PointerType
- def __init__(self, value=None):
- if value is None:
- self.is_null = True
- else:
- self.value = value
- # we should later check why exactly this is the case
- try:
- type(self).__dict__['_type_']
- except KeyError:
- raise TypeError("%s has no _type_" % self.__class__)
+ def getvalue(self):
+ return self._array
+
+ value = property(getvalue)
+
+ def getcontents(self):
+ return self._type_.from_address(self._array.buffer)
+
+ def setcontents(self, value):
+ self._array = self._ffiarray.fromaddress(value._array.buffer, 1)
+
+ def __getitem__(self, item):
+ return self._array[item]
+
+ def __setitem__(self, item, value):
+ self._array[item] = value
+
+ contents = property(getcontents, setcontents)
Modified: pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/lib/_ctypes/primitive.py Thu Jan 10 11:55:04 2008
@@ -2,6 +2,8 @@
SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv"
+from _ctypes.basics import _CData
+
class NULL(object):
pass
NULL = NULL()
@@ -42,20 +44,27 @@
raise ValueError('%s is not a type character' % (tp))
default = TP_TO_DEFAULT[tp]
ffitp = TP_TO_FFITP.get(tp, tp)
- ffistruct = _ffi.Structure([("value", ffitp)])
- def __init__(self, value=DEFAULT_VALUE):
- self._struct = ffistruct()
- if value is not DEFAULT_VALUE:
- self._struct.value = value
+ ffiarray = _ffi.Array(ffitp)
+ def __init__(self, value=DEFAULT_VALUE, address=DEFAULT_VALUE):
+ if address is not DEFAULT_VALUE:
+ self._array = ffiarray.fromaddress(address, 1)
+ else:
+ self._array = ffiarray(1)
+ if value is not DEFAULT_VALUE:
+ self._array[0] = value
dct['__init__'] = __init__
result = type.__new__(self, name, bases, dct)
- result._ffistruct = ffistruct
+ result._ffiarray = ffiarray
+ result._ffiletter = result._type_
return result
+ def from_address(self, address):
+ return self(address=address)
+
def __mul__(self, other):
pass
-class _SimpleCData(object):
+class _SimpleCData(_CData):
__metaclass__ = SimpleType
_type_ = 'i'
def from_param(cls, *args, **kwargs):
@@ -63,10 +72,10 @@
from_param = classmethod(from_param)
def _getvalue(self):
- return self._struct.value
+ return self._array[0]
def _setvalue(self, val):
- self._struct.value = value
+ self._array[0] = value
value = property(_getvalue, _setvalue)
def __repr__(self):
More information about the Pypy-commit
mailing list