Thomas Heller schrieb: >> Sturla Molden schrieb: >>> On 3/26/2009 12:41 PM, Jens Rantil wrote: >>> >>>> Wouldn't my code, or a tweak of it, be a nice feature in >>>> numpy.ctypeslib? Is this the wrong channel for proposing things like >>>> this? >>> >>> If you look at >>> >>> http://svn.scipy.org/svn/numpy/trunk/numpy/ctypeslib.py >>> >>> you will see that it does almost the same. I think it would be better to >>> work out why ndpointer fails as restype and patch that. >> > > Thomas Heller schrieb: > >> ndpointer(...), which returns an _nptr instance, does not work as restype >> because neither it is a base class of one of the ctypes base types like >> ctypes.c_void_p, also it is not callable with one argument. >> >> There are two ways to fix this. The first one is to make the _nptr callable > [...] >> >> The other way is to make _nptr a subclass of ctypes.c_void_p, >> the result that the foreign function call returns will then be >> an instance of this class. Unfortunately, ctypes will not call >> __new__() to create this instance; so a custom __new__() implementation >> cannot return a numpy array and we are left with the _nptr instance. >> The only way to create and access the numpy array is to construct >> and return one from a method call on the _nptr instance, or a property >> on the _nptr instance. >> Ok, .errcheck could call that method and return the result. >> > Well, looking into the ctypes sources trying to invent a new protocol for > the restype attribute I found out that THERE IS ALREADY a mechanism for it, > but I had totally forgotten that it exists. > > When the .restype attribute of a function is set to a SUBCLASS of a > ctypes type (c_void_p for example), an instance of this subclass is created. > After that, if this instance has a _check_retval_ method, this method is > called > and the result of this call is returned. So, it is indeed possible to create > a class that can be assigned to .restype, and which can convert the return > value > of a function to whatever we like. > > I will prepare a patch for numpy.ctypeslib. >
It seems there isn't much interest in a patch - true? Anyway, before it gets totally forgotten, here is the patch. The _ndptr._check_retval_ method should probably be extended to handle the memory management of the result. diff -u c:\python25\lib\site-packages\numpy\ctypeslib.py.orig c:\python25\lib\site-packages\numpy\ctypeslib.py.new --- c:\python25\lib\site-packages\numpy\ctypeslib.py.orig Fri Apr 03 19:35:10 2009 +++ c:\python25\lib\site-packages\numpy\ctypeslib.py.new Fri Apr 03 19:35:10 2009 @@ -69,10 +69,12 @@ as_ctypes = _dummy as_array = _dummy from numpy import intp as c_intp + _ndptr_base = object else: import numpy.core._internal as nic c_intp = nic._getintp_ctype() del nic + _ndptr_base = ctypes.c_void_p # Adapted from Albert Strasheim def load_library(libname, loader_path): @@ -130,7 +132,24 @@ return res -class _ndptr(object): +class _ndptr(_ndptr_base): + + def _check_retval_(self): + """This method is called when this class is used as .restype + attribute for a dll function. It constructs a numpy array from + a void pointer.""" + return array(self) + + @property + def __array_interface__(self): + return {'descr': self._dtype_.descr, + '__ref': self, + 'strides': None, + 'shape': self._shape_, + 'version': 3, + 'typestr': self._dtype_.descr[0][1], + 'data': (self.value, False), + } def from_param(cls, obj): if not isinstance(obj, ndarray): -- Thanks, Thomas _______________________________________________ Numpy-discussion mailing list Numpy-discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion