[Numpy-discussion] numpy.ctypeslib.ndpointer and the restype attribute [patch]
Thomas Heller
theller@ctypes....
Fri Apr 3 14:38:18 CDT 2009
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
More information about the Numpy-discussion
mailing list