Author: Alex Gaynor <[email protected]>
Branch: numpypy-ctypes
Changeset: r52596:69d8667c5a60
Date: 2012-02-17 21:16 -0500
http://bitbucket.org/pypy/pypy/changeset/69d8667c5a60/
Log: Added ctypes to arrays. Works, except 2 failing tests.
diff --git a/lib_pypy/numpypy/core/_internal.py
b/lib_pypy/numpypy/core/_internal.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpypy/core/_internal.py
@@ -0,0 +1,78 @@
+#A place for code to be called from C-code
+# that implements more complicated stuff.
+
+def _getintp_ctype():
+ from _numpypy import dtype
+ val = _getintp_ctype.cache
+ if val is not None:
+ return val
+ char = dtype('p').char
+ import ctypes
+ if (char == 'i'):
+ val = ctypes.c_int
+ elif char == 'l':
+ val = ctypes.c_long
+ elif char == 'q':
+ val = ctypes.c_longlong
+ else:
+ val = ctypes.c_long
+ _getintp_ctype.cache = val
+ return val
+_getintp_ctype.cache = None
+
+# Used for .ctypes attribute of ndarray
+
+class _missing_ctypes(object):
+ def cast(self, num, obj):
+ return num
+
+ def c_void_p(self, num):
+ return num
+
+class _ctypes(object):
+ def __init__(self, array, ptr=None):
+ try:
+ import ctypes
+ self._ctypes = ctypes
+ except ImportError:
+ self._ctypes = _missing_ctypes()
+ self._arr = array
+ self._data = ptr
+ if self._arr.ndim == 0:
+ self._zerod = True
+ else:
+ self._zerod = False
+
+ def data_as(self, obj):
+ return self._ctypes.cast(self._data, obj)
+
+ def shape_as(self, obj):
+ if self._zerod:
+ return None
+ return (obj*self._arr.ndim)(*self._arr.shape)
+
+ def strides_as(self, obj):
+ if self._zerod:
+ return None
+ return (obj*self._arr.ndim)(*self._arr.strides)
+
+ def get_data(self):
+ return self._data
+
+ def get_shape(self):
+ if self._zerod:
+ return None
+ return (_getintp_ctype()*self._arr.ndim)(*self._arr.shape)
+
+ def get_strides(self):
+ if self._zerod:
+ return None
+ return (_getintp_ctype()*self._arr.ndim)(*self._arr.strides)
+
+ def get_as_parameter(self):
+ return self._ctypes.c_void_p(self._data)
+
+ data = property(get_data, None, doc="c-types data")
+ shape = property(get_shape, None, doc="c-types shape")
+ strides = property(get_strides, None, doc="c-types strides")
+ _as_parameter_ = property(get_as_parameter, None, doc="_as parameter_")
diff --git a/pypy/module/micronumpy/appbridge.py
b/pypy/module/micronumpy/appbridge.py
--- a/pypy/module/micronumpy/appbridge.py
+++ b/pypy/module/micronumpy/appbridge.py
@@ -2,28 +2,34 @@
from pypy.rlib.objectmodel import specialize
class AppBridgeCache(object):
+ w_numpypy_core__methods_module = None
w__var = None
w__std = None
- w_module = None
w_array_repr = None
w_array_str = None
+ w_numpypy_core__internal_module = None
+ w__ctypes = None
+
def __init__(self, space):
self.w_import = space.appexec([], """():
- def f():
+ def f(module):
import sys
- __import__('numpypy.core._methods')
- return sys.modules['numpypy.core._methods']
+ __import__(module)
+ return sys.modules[module]
return f
""")
-
- @specialize.arg(2)
- def call_method(self, space, name, *args):
- w_meth = getattr(self, 'w_' + name)
+
+ @specialize.arg(2, 3)
+ def call_method(self, space, module, name, *args):
+ module_attr = "w_" + module.replace(".", "_") + "_module"
+ meth_attr = "w_" + name
+ w_meth = getattr(self, meth_attr)
if w_meth is None:
- if self.w_module is None:
- self.w_module = space.call_function(self.w_import)
- w_meth = space.getattr(self.w_module, space.wrap(name))
+ if getattr(self, module_attr) is None:
+ w_mod = space.call_function(self.w_import, space.wrap(module))
+ setattr(self, module_attr, w_mod)
+ w_meth = space.getattr(getattr(self, module_attr),
space.wrap(name))
setattr(self, 'w_' + name, w_meth)
return space.call_function(w_meth, *args)
diff --git a/pypy/module/micronumpy/interp_dtype.py
b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -121,11 +121,14 @@
itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
shape = GetSetProperty(W_Dtype.descr_get_shape),
name = interp_attrproperty('name', cls=W_Dtype),
+ char = interp_attrproperty("char", cls=W_Dtype),
)
W_Dtype.typedef.acceptable_as_base_class = False
class DtypeCache(object):
def __init__(self, space):
+ ptr_size = rffi.sizeof(rffi.VOIDP)
+
self.w_booldtype = W_Dtype(
types.Bool(),
num=0,
@@ -173,6 +176,7 @@
kind=SIGNEDLTR,
name="int32",
char="i",
+ aliases = ["p"] if ptr_size == 4 else [],
w_box_type=space.gettypefor(interp_boxes.W_Int32Box),
)
self.w_uint32dtype = W_Dtype(
@@ -211,6 +215,7 @@
name="int64",
char="q",
w_box_type=space.gettypefor(interp_boxes.W_Int64Box),
+ aliases = ["p"] if ptr_size == 8 else [],
alternate_constructors=[space.w_long],
)
self.w_uint64dtype = W_Dtype(
diff --git a/pypy/module/micronumpy/interp_numarray.py
b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -256,9 +256,23 @@
return
self.get_concrete().setshape(space, new_shape)
+ @jit.unroll_safe
+ def descr_get_strides(self, space):
+ return space.newtuple([space.wrap(i) for i in self.strides])
+
def descr_get_size(self, space):
return space.wrap(self.size)
+ def descr_get_ctypes(self, space):
+ if not self.shape:
+ raise OperationError(space.w_TypeError, space.wrap("Can't get the
ctypes of a scalar yet."))
+ concrete = self.get_concrete()
+ storage = concrete.storage
+ addr = rffi.cast(lltype.Signed, storage)
+ return get_appbridge_cache(space).call_method(space,
+ "numpypy.core._internal", "_ctypes", self, space.wrap(addr)
+ )
+
def descr_copy(self, space):
return self.copy(space)
@@ -513,12 +527,14 @@
return space.div(self.descr_sum_promote(space, w_axis), w_denom)
def descr_var(self, space, w_axis=None):
- return get_appbridge_cache(space).call_method(space, '_var', self,
- w_axis)
+ return get_appbridge_cache(space).call_method(space,
+ 'numpypy.core._methods', '_var', self, w_axis
+ )
def descr_std(self, space, w_axis=None):
- return get_appbridge_cache(space).call_method(space, '_std', self,
- w_axis)
+ return get_appbridge_cache(space).call_method(space,
+ 'numpypy.core._methods', '_std', self, w_axis
+ )
def descr_fill(self, space, w_value):
concr = self.get_concrete_or_scalar()
@@ -1291,10 +1307,12 @@
dtype = GetSetProperty(BaseArray.descr_get_dtype),
shape = GetSetProperty(BaseArray.descr_get_shape,
BaseArray.descr_set_shape),
+ strides = GetSetProperty(BaseArray.descr_get_strides),
size = GetSetProperty(BaseArray.descr_get_size),
ndim = GetSetProperty(BaseArray.descr_get_ndim),
itemsize = GetSetProperty(BaseArray.descr_get_itemsize),
nbytes = GetSetProperty(BaseArray.descr_get_nbytes),
+ ctypes = GetSetProperty(BaseArray.descr_get_ctypes),
T = GetSetProperty(BaseArray.descr_get_transpose),
transpose = interp2app(BaseArray.descr_get_transpose),
diff --git a/pypy/module/micronumpy/test/test_base.py
b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -14,7 +14,7 @@
import numpy
sys.modules['numpypy'] = numpy
sys.modules['_numpypy'] = numpy
- cls.space = gettestobjspace(usemodules=['micronumpy'])
+ cls.space = gettestobjspace(usemodules=['micronumpy', '_ffi',
'_rawffi'])
class TestSignature(object):
def test_binop_signature(self, space):
diff --git a/pypy/module/micronumpy/test/test_numarray.py
b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1709,6 +1709,25 @@
assert (a + a).item(1) == 4
raises(ValueError, "array(5).item(1)")
+ def test_ctypes(self):
+ import gc
+ from _numpypy import array
+
+ a = array([1, 2, 3, 4, 5])
+ assert a.ctypes._data == a.__array_interface__["data"][0]
+ assert a is a.ctypes._arr
+
+ shape = a.ctypes.get_shape()
+ assert len(shape) == 1
+ assert shape[0] == 5
+
+ strides = a.ctypes.get_strides()
+ assert len(strides) == 1
+ assert strides[0] == 1
+
+ a = array(2)
+ raises(TypeError, lambda: a.ctypes)
+
class AppTestSupport(BaseNumpyAppTest):
def setup_class(cls):
import struct
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit