@@ -319,120 +319,47 @@ def ndpointer(dtype=None, ndim=None, shape=None, flags=None):
319
319
_pointer_type_cache [(dtype , shape , ndim , num )] = klass
320
320
return klass
321
321
322
- if ctypes is not None :
323
- ct = ctypes
324
- ################################################################
325
- # simple types
326
-
327
- # maps the numpy typecodes like '<f8' to simple ctypes types like
328
- # c_double. Filled in by prep_simple.
329
- _typecodes = {}
330
-
331
- def prep_simple (simple_type , dtype ):
332
- """Given a ctypes simple type, construct and attach an
333
- __array_interface__ property to it if it does not yet have one.
334
- """
335
- try : simple_type .__array_interface__
336
- except AttributeError : pass
337
- else : return
338
-
339
- typestr = _dtype (dtype ).str
340
- _typecodes [typestr ] = simple_type
341
-
342
- def __array_interface__ (self ):
343
- return {'descr' : [('' , typestr )],
344
- '__ref' : self ,
345
- 'strides' : None ,
346
- 'shape' : (),
347
- 'version' : 3 ,
348
- 'typestr' : typestr ,
349
- 'data' : (ct .addressof (self ), False ),
350
- }
351
-
352
- simple_type .__array_interface__ = property (__array_interface__ )
353
322
323
+ def _get_typecodes ():
324
+ """ Return a dictionary mapping __array_interface__ formats to ctypes types """
325
+ ct = ctypes
354
326
simple_types = [
355
- (( ct .c_byte , ct .c_short , ct .c_int , ct .c_long , ct .c_longlong ), "i" ) ,
356
- (( ct .c_ubyte , ct.c_ushort , ct .c_uint , ct .c_ulong , ct .c_ulonglong ), "u" ) ,
357
- (( ct .c_float , ct .c_double ), "f" ) ,
327
+ ct .c_byte , ct .c_short , ct .c_int , ct .c_long , ct .c_longlong ,
328
+ ct .c_ubyte , ct .c_ushort , ct .c_uint , ct .c_ulong , ct .c_ulonglong ,
329
+ ct .c_float , ct .c_double ,
358
330
]
359
331
360
- # Prep that numerical ctypes types:
361
- for types , code in simple_types :
362
- for tp in types :
363
- prep_simple (tp , "%c%d" % (code , ct .sizeof (tp )))
332
+ return {_dtype (ctype ).str : ctype for ctype in simple_types }
364
333
365
- ################################################################
366
- # array types
367
334
368
- _ARRAY_TYPE = type (ct .c_int * 1 )
335
+ def _ctype_ndarray (element_type , shape ):
336
+ """ Create an ndarray of the given element type and shape """
337
+ for dim in shape [::- 1 ]:
338
+ element_type = element_type * dim
339
+ return element_type
369
340
370
- def prep_array (array_type ):
371
- """Given a ctypes array type, construct and attach an
372
- __array_interface__ property to it if it does not yet have one.
373
- """
374
- try : array_type .__array_interface__
375
- except AttributeError : pass
376
- else : return
377
-
378
- shape = []
379
- ob = array_type
380
- while type (ob ) is _ARRAY_TYPE :
381
- shape .append (ob ._length_ )
382
- ob = ob ._type_
383
- shape = tuple (shape )
384
- ai = ob ().__array_interface__
385
- descr = ai ['descr' ]
386
- typestr = ai ['typestr' ]
387
-
388
- def __array_interface__ (self ):
389
- return {'descr' : descr ,
390
- '__ref' : self ,
391
- 'strides' : None ,
392
- 'shape' : shape ,
393
- 'version' : 3 ,
394
- 'typestr' : typestr ,
395
- 'data' : (ct .addressof (self ), False ),
396
- }
397
-
398
- array_type .__array_interface__ = property (__array_interface__ )
399
-
400
- def prep_pointer (pointer_obj , shape ):
401
- """Given a ctypes pointer object, construct and
402
- attach an __array_interface__ property to it if it does not
403
- yet have one.
404
- """
405
- try : pointer_obj .__array_interface__
406
- except AttributeError : pass
407
- else : return
408
-
409
- contents = pointer_obj .contents
410
- dtype = _dtype (type (contents ))
411
-
412
- inter = {'version' : 3 ,
413
- 'typestr' : dtype .str ,
414
- 'data' : (ct .addressof (contents ), False ),
415
- 'shape' : shape }
416
-
417
- pointer_obj .__array_interface__ = inter
418
341
419
- ################################################################
420
- # public functions
342
+ if ctypes is not None :
343
+ _typecodes = _get_typecodes ()
421
344
422
345
def as_array (obj , shape = None ):
423
- """Create a numpy array from a ctypes array or a ctypes POINTER.
346
+ """
347
+ Create a numpy array from a ctypes array or POINTER.
348
+
424
349
The numpy array shares the memory with the ctypes object.
425
350
426
- The size parameter must be given if converting from a ctypes POINTER.
427
- The size parameter is ignored if converting from a ctypes array
351
+ The shape parameter must be given if converting from a ctypes POINTER.
352
+ The shape parameter is ignored if converting from a ctypes array
428
353
"""
429
- tp = type (obj )
430
- try : tp .__array_interface__
431
- except AttributeError :
432
- if hasattr (obj , 'contents' ):
433
- prep_pointer (obj , shape )
434
- else :
435
- prep_array (tp )
354
+ if isinstance (obj , ctypes ._Pointer ):
355
+ # convert pointers to an array of the desired shape
356
+ if shape is None :
357
+ raise TypeError (
358
+ 'as_array() requires a shape argument when called on a '
359
+ 'pointer' )
360
+ p_arr_type = ctypes .POINTER (_ctype_ndarray (obj ._type_ , shape ))
361
+ obj = ctypes .cast (obj , p_arr_type ).contents
362
+
436
363
return array (obj , copy = False )
437
364
438
365
def as_ctypes (obj ):
@@ -446,9 +373,7 @@ def as_ctypes(obj):
446
373
addr , readonly = ai ["data" ]
447
374
if readonly :
448
375
raise TypeError ("readonly arrays unsupported" )
449
- tp = _typecodes [ai ["typestr" ]]
450
- for dim in ai ["shape" ][::- 1 ]:
451
- tp = tp * dim
376
+ tp = _ctype_ndarray (_typecodes [ai ["typestr" ]], ai ["shape" ])
452
377
result = tp .from_address (addr )
453
378
result .__keep = ai
454
379
return result
0 commit comments