8000 Remove _as_parameter_ attribute from arrays and add it to the ctypes … · numpy/numpy@eee00f8 · GitHub
[go: up one dir, main page]

Skip to content

Commit eee00f8

Browse files
committed
Remove _as_parameter_ attribute from arrays and add it to the ctypes object. Create an ndpointer class factory to return classes that check for specific array types. These can be used in argtypes list to ctypes functions.
1 parent 8e24ef8 commit eee00f8

File tree

3 files changed

+54
-23
lines changed

3 files changed

+54
-23
lines changed

numpy/core/_internal.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,21 +208,30 @@ def _getintp_ctype():
208208
_getintp_ctype.cache = None
209209

210210
# Used for .ctypes attribute of ndarray
211+
212+
class _missing_ctypes(object):
213+
def cast(self, num, obj):
214+
return num
215+
216+
def c_void_p(self, num):
217+
return num
218+
211219
class _ctypes(object):
212-
def __init__(self, array):
220+
def __init__(self, array, ptr=None):
213221
try:
214222
import ctypes
215223
self._ctypes = ctypes
216224
except ImportError:
217-
raise AttributeError, "ctypes not available"
225+
self._ctypes = _missing_ctypes()
218226
self._arr = array
227+
self._data = ptr
219228
if self._arr.ndim == 0:
220229
self._zerod = True
221230
else:
222231
self._zerod = False
223232

224233
def data_as(self, obj):
225-
return self._ctypes.cast(self._arr._as_parameter_, obj)
234+
return self._ctypes.cast(self._data, obj)
226235

227236
def shape_as(self, obj):
228237
if self._zerod:
@@ -235,7 +244,7 @@ def strides_as(self, obj):
235244
return (obj*self._arr.ndim)(*self._arr.strides)
236245

237246
def get_data(self):
238-
return self._ctypes.c_void_p(self._arr._as_parameter_)
247+
return self._ctypes.c_void_p(self._data)
239248

240249
def get_shape(self):
241250
if self._zerod:
@@ -246,7 +255,11 @@ def get_strides(self):
246255
if self._zerod:
247256
return None
248257
return (_getintp_ctype()*self._arr.ndim)(*self._arr.strides)
249-
258+
259+
def get_as_parameter(self):
260+
return self._data
261+
250262
data = property(get_data, None, doc="c-types data")
251263
shape = property(get_shape, None, doc="c-types shape")
252264
strides = property(get_strides, None, doc="c-types strides")
265+
_as_parameter_ = property(get_as_parameter, None, doc="_as parameter_")

numpy/core/src/arrayobject.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5829,13 +5829,8 @@ static PyObject *
58295829
array_ctypes_get(PyArrayObject *self)
58305830
{
58315831
return PyObject_CallMethod(_numpy_internal, "_ctypes",
5832-
"O", self);
5833-
}
5834-
5835-
static PyObject *
5836-
array_as_parameter_get(PyArrayObject *self)
5837-
{
5838-
return PyLong_FromVoidPtr(self->data);
5832+
"ON", self,
5833+
PyLong_FromVoidPtr(self->data));
58395834
}
58405835

58415836
static PyObject *
@@ -6413,9 +6408,6 @@ static PyGetSetDef array_getsetlist[] = {
64136408
{"ctypes",
64146409
(getter)array_ctypes_get,
64156410
NULL, NULL},
6416-
{"_as_parameter_",
6417-
(getter)array_as_parameter_get,
6418-
NULL, NULL},
64196411
{"T",
64206412
(getter)array_transpose_get,
64216413
NULL, NULL},
@@ -11062,11 +11054,11 @@ static PyTypeObject PyArrayDescr_Type = {
1106211054
(reprfunc)arraydescr_repr, /* tp_repr */
1106311055
0, /* tp_as_number */
1106411056
0, /* tp_as_sequence */
11065-
&descr_as_mapping, /* tp_as_mapping */
11066-
0, /* tp_hash */
11057+
&descr_as_mapping, /* tp_as_mapping */
11058+
(hashfunc)_Py_HashPointer, /* tp_hash */
1106711059
0, /* tp_call */
11068-
(reprfunc)arraydescr_str, /* tp_str */
11069-
0, /* tp_getattro */
11060+
(reprfunc)arraydescr_str, /* tp_str */
11061+
0, /* tp_getattro */
1107011062
0, /* tp_setattro */
1107111063
0, /* tp_as_buffer */
1107211064
Py_TPFLAGS_DEFAULT, /* tp_flags */
@@ -11075,8 +11067,8 @@ static PyTypeObject PyArrayDescr_Type = {
1107511067
0, /* tp_clear */
1107611068
(richcmpfunc)arraydescr_richcompare, /* tp_richcompare */
1107711069
0, /* tp_weaklistoffset */
11078-
0, /* tp_iter */
11079-
0, /* tp_iternext */
11070+
0, /* tp_iter */
11071+
0, /* tp_iternext */
1108011072
arraydescr_methods, /* tp_methods */
1108111073
arraydescr_members, /* tp_members */
1108211074
arraydescr_getsets, /* tp_getset */

numpy/lib/utils.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
__all__ = ['issubclass_', 'get_numpy_include', 'issubsctype',
99
'issubdtype', 'deprecate', 'get_numarray_include',
10-
'get_include', 'ctypes_load_library', 'info',
11-
'source', 'who']
10+
'get_include', 'ctypes_load_library', 'ndpointer',
11+
'info', 'source', 'who']
1212

1313
def issubclass_(arg1, arg2):
1414
try:
@@ -76,6 +76,32 @@ def ctypes_load_library(libname, loader_path):
7676
libpath = os.path.join(libdir, libname)
7777
return ctypes.cdll[libpath]
7878

79+
class _ndptr(object):
80+
def from_param(cls, obj):
81+
if not isinstance(obj, ndarray):
82+
raise TypeError("argument must be an ndarray")
83+
if obj.dtype != cls._dtype_:
84+
raise TypeError("array must have data type", cls._dtype_)
85+
return obj.ctypes
86+
from_param = classmethod(from_param)
87+
88+
# Factory for a type-checking object with from_param defined
89+
_pointer_type_cache = {}
90+
def ndpointer(datatype):
91+
datatype = dtype(datatype)
92+
try:
93+
return _pointer_type_cache[datatype]
94+
except KeyError:
95+
pass
96+
if datatype.names:
97+
name = str(id(datatype))
98+
else:
99+
name = datatype.str
100+
klass = type("ndpointer_%s"%name, (_ndptr,),
101+
{"_dtype_": datatype})
102+
_pointer_type_cache[datatype] = klass
103+
return klass
104+
79105

80106
if sys.version_info < (2, 4):
81107
# Can't set __name__ in 2.3

0 commit comments

Comments
 (0)
0