[Numpy-svn] r4752 - trunk/numpy
numpy-svn at scipy.org
numpy-svn at scipy.org
Thu Jan 24 23:22:04 EST 2008
Author: oliphant
Date: 2008-01-24 22:21:51 -0600 (Thu, 24 Jan 2008)
New Revision: 4752
Modified:
trunk/numpy/ctypeslib.py
Log:
Add Thomas Heller's ctypes_array code to ctypeslib providing the functions as_ctypes and as_array to convert back and forth between numpy arrays and ctypes objects.
Modified: trunk/numpy/ctypeslib.py
===================================================================
--- trunk/numpy/ctypeslib.py 2008-01-24 09:57:22 UTC (rev 4751)
+++ trunk/numpy/ctypeslib.py 2008-01-25 04:21:51 UTC (rev 4752)
@@ -1,8 +1,8 @@
__all__ = ['load_library', 'ndpointer', 'test', 'ctypes_load_library',
- 'c_intp']
+ 'c_intp', 'as_ctypes', 'as_array']
import sys, os
-from numpy import integer, ndarray, dtype as _dtype, deprecate
+from numpy import integer, ndarray, dtype as _dtype, deprecate, array
from numpy.core.multiarray import _flagdict, flagsobj
try:
@@ -15,6 +15,8 @@
raise ImportError, "ctypes is not available."
ctypes_load_library = _dummy
load_library = _dummy
+ as_ctypes = _dummy
+ as_array = _dummy
from numpy import intp as c_intp
else:
import numpy.core._internal as nic
@@ -160,6 +162,118 @@
_pointer_type_cache[dtype] = klass
return klass
+if ctypes is not None:
+ ct = ctypes
+ ################################################################
+ # simple types
+
+ # maps the numpy typecodes like '<f8' to simple ctypes types like
+ # c_double. Filled in by prep_simple.
+ _typecodes = {}
+
+ def prep_simple(simple_type, typestr):
+ """Given a ctypes simple type, construct and attach an
+ __array_interface__ property to it if it does not yet have one.
+ """
+ try: simple_type.__array_interface__
+ except AttributeError: pass
+ else: return
+
+ _typecodes[typestr] = simple_type
+
+ def __array_interface__(self):
+ return {'descr': [('', typestr)],
+ '__ref': self,
+ 'strides': None,
+ 'shape': (),
+ 'version': 3,
+ 'typestr': typestr,
+ 'data': (ct.addressof(self), False),
+ }
+
+ simple_type.__array_interface__ = property(__array_interface__)
+
+ if sys.byteorder == "little":
+ TYPESTR = "<%c%d"
+ else:
+ TYPESTR = ">%c%d"
+
+ simple_types = [
+ ((ct.c_byte, ct.c_short, ct.c_int, ct.c_long, ct.c_longlong), "i"),
+ ((ct.c_ubyte, ct.c_ushort, ct.c_uint, ct.c_ulong, ct.c_ulonglong), "u"),
+ ((ct.c_float, ct.c_double), "f"),
+ ]
+
+ # Prep that numerical ctypes types:
+ for types, code in simple_types:
+ for tp in types:
+ prep_simple(tp, TYPESTR % (code, ct.sizeof(tp)))
+
+ ################################################################
+ # array types
+
+ _ARRAY_TYPE = type(ct.c_int * 1)
+
+ def prep_array(array_type):
+ """Given a ctypes array type, construct and attach an
+ __array_interface__ property to it if it does not yet have one.
+ """
+ try: array_type.__array_interface__
+ except AttributeError: pass
+ else: return
+
+ shape = []
+ ob = array_type
+ while type(ob) == _ARRAY_TYPE:
+ shape.append(ob._length_)
+ ob = ob._type_
+ shape = tuple(shape)
+ ai = ob().__array_interface__
+ descr = ai['descr']
+ typestr = ai['typestr']
+
+ def __array_interface__(self):
+ return {'descr': descr,
+ '__ref': self,
+ 'strides': None,
+ 'shape': shape,
+ 'version': 3,
+ 'typestr': typestr,
+ 'data': (ct.addressof(self), False),
+ }
+
+ array_type.__array_interface__ = property(__array_interface__)
+
+ ################################################################
+ # public functions
+
+ def as_array(obj):
+ """Create a numpy array from a ctypes array. The numpy array
+ shares the memory with the ctypes object."""
+ tp = type(obj)
+ try: tp.__array_interface__
+ except AttributeError: prep_array(tp)
+ return array(obj, copy=False)
+
+ def as_ctypes(obj):
+ """Create and return a ctypes object from a numpy array. Actually
+ anything that exposes the __array_interface__ is accepted."""
+ ai = obj.__array_interface__
+ if ai["strides"]:
+ raise TypeError("strided arrays not supported")
+ if ai["version"] != 3:
+ raise TypeError("only __array_interface__ version 3 supported")
+ addr, readonly = ai["data"]
+ if readonly:
+ raise TypeError("readonly arrays unsupported")
+ tp = _typecodes[ai["typestr"]]
+ for dim in ai["shape"][::-1]:
+ tp = tp * dim
+ result = tp.from_address(addr)
+ result.__keep = ai
+ return result
+
+
def test(level=1, verbosity=1):
from numpy.testing import NumpyTest
return NumpyTest().test(level, verbosity)
More information about the Numpy-svn
mailing list