Package ivs :: Package aux :: Module numpyctypes
[hide private]
[frames] | no frames]

Source Code for Module ivs.aux.numpyctypes

  1  """ 
  2  Module to convert a numpy array to a ctypes struct. 
  3  This struct can then be passed to a native C library. 
  4   
  5  Author: Joris De Ridder 
  6  """ 
  7   
  8  import numpy as np 
  9  import ctypes as C 
 10   
 11   
 12   
 13  ctypesDict = {'d' : C.c_double, 
 14                'b' : C.c_char, 
 15                'h' : C.c_short, 
 16                'i' : C.c_int, 
 17                'l' : C.c_long, 
 18                'q' : C.c_longlong, 
 19                'B' : C.c_ubyte, 
 20                'H' : C.c_ushort, 
 21                'I' : C.c_uint, 
 22                'L' : C.c_ulong, 
 23                'Q' : C.c_ulonglong} 
 24                 
 25   
 26   
 27   
 28   
 29   
30 -def c_ndarray(a, dtype = None, ndim = None, shape = None, requirements = None):
31 32 """ 33 Returns a ctypes structure of the array 'a' 34 containing the arrays info (data, shape, strides, ndim). 35 A check is made to ensure that the array has the specified dtype 36 and requirements. 37 38 Example: 39 40 >>> myArray = np.arange(10.0) 41 >>> myCstruct = c_ndarray(myArray, dtype=np.double, ndim = 3, shape = (4,3,2), 42 ... requirements = ['c_contiguous']) 43 44 @param a: the numpy array to be converted 45 @type a: ndarray 46 @param dtype: the required dtype of the array, convert if it doesn't match 47 @type dtype: numpy dtype 48 @param ndim: the required number of axes of the array, 49 complain if it doesn't match 50 @type ndim: integer 51 @param shape: required shape of the array, complain if it doesn't match 52 @type shape: tuple 53 @param requirements: "ensurearray", "aligned", "fortran", "f_contiguous", 54 or "c_contiguous". Convert if it doesn't match. 55 @type requirements: list 56 @return: ctypes structure with the fields: 57 - data: pointer to the data : the type is determined with the 58 dtype of the array, and with ctypesDict. 59 - shape: pointer to long array : size of each of the dimensions 60 - strides: pointer to long array : strides in elements (not bytes) 61 @rtype: ctypes structure 62 63 """ 64 65 if not requirements: 66 67 # Also allow derived classes of ndarray 68 69 array = np.asanyarray(a, dtype=dtype) 70 71 else: 72 73 # Convert requirements to captial letter codes: 74 # (ensurearray' -> 'E'; 'aligned' -> 'A' 75 # 'fortran', 'f_contiguous', 'f' -> 'F' 76 # 'contiguous', 'c_contiguous', 'c' -> 'C') 77 78 requirements = [x[0].upper() for x in requirements] 79 subok = (0 if 'E' in requirements else 1) 80 81 # Make from 'a' an ndarray with the specified dtype, but don't copy the 82 # data (yet). This also ensures that the .flags attribute is present. 83 84 array = np.array(a, dtype=dtype, copy=False, subok=subok) 85 86 # See if copying all data is really necessary. 87 # Note: 'A' = (A)ny = only (F) it is was already (F) 88 89 copychar = 'A' 90 if 'F' in requirements: 91 copychar = 'F' 92 elif 'C' in requirements: 93 copychar = 'C' 94 95 for req in requirements: 96 if not array.flags[req]: 97 array = array.copy(copychar) 98 break 99 100 101 # If required, check the number of axes and the shape of the array 102 103 if ndim is not None: 104 if array.ndim != ndim: 105 raise TypeError, "Array has wrong number of axes" 106 107 if shape is not None: 108 if array.shape != shape: 109 raise TypeError, "Array has wrong shape" 110 111 # Define a class that serves as interface of an ndarray to ctypes. 112 # Part of the type depends on the array's dtype. 113 114 class ndarrayInterfaceToCtypes(C.Structure): 115 pass
116 117 typechar = array.dtype.char 118 119 if typechar in ctypesDict: 120 ndarrayInterfaceToCtypes._fields_ = \ 121 [("data", C.POINTER(ctypesDict[typechar])), 122 ("shape" , C.POINTER(C.c_long)), 123 ("strides", C.POINTER(C.c_long))] 124 else: 125 raise TypeError, "dtype of input ndarray not supported" 126 127 # Instantiate the interface class and attach the ndarray's internal info. 128 # Ctypes does automatic conversion between (c_long * #) arrays and POINTER(c_long). 129 130 ndarrayInterface = ndarrayInterfaceToCtypes() 131 ndarrayInterface.data = array.ctypes.data_as(C.POINTER(ctypesDict[typechar])) 132 ndarrayInterface.shape = (C.c_long * array.ndim)(*array.shape) 133 ndarrayInterface.strides = (C.c_long * array.ndim)(*array.strides) 134 for n in range(array.ndim): 135 ndarrayInterface.strides[n] /= array.dtype.itemsize 136 137 return ndarrayInterface 138