ctypes.cast在python2中工作,在python3中抛出ArgumentError



我遇到了一个问题,我的ctypes代码在python2中工作,但在python3中失败。

我失败的函数是arrptr_to_np,它试图在外部c库中创建一个数组并将其加载到numpy数组中。

函数看起来像这样

def arrptr_to_np(c_arrptr, shape, arr_t, dtype):
    """
    Casts an array pointer from C to numpy
    Args:
        c_arrpt (uint64): a pointer to an array returned from C
        shape (tuple): shape of the underlying array being pointed to
        arr_t (PyCSimpleType): the ctypes datatype of c_arrptr
        dtype (dtype): numpy datatype the array will be to cast into
    """ 
    byte_t = ctypes.c_char
    itemsize_ = dtype().itemsize
    dtype_t = byte_t * itemsize_
    dtype_ptr_t = C.POINTER(dtype_t)  # size of each item
    typed_c_arrptr = c_arrptr.astype(int)
    c_arr = C.cast(typed_c_arrptr, dtype_ptr_t)   # cast to ctypes
    np_arr = np.ctypeslib.as_array(c_arr, shape)
    np_arr.dtype = dtype
    return np_arr

这些是我正在使用的示例中变量的值

varname - value - type(var)

c_arrptr - 20622304 - numpy.uint64

shape - (506,6) - tuple

arr_t - numpy. ctypelib .ndpointer_

错误告诉您,第一个参数无法转换为ctypes.c_void_p。即typed_c_arrptr不能被转换。

这是因为astype()在两个版本的Python中工作方式不同。在Python 3中,有

>>> isinstance(np.uint64(12345).astype(int), int)
False

,因此ctypes不知道如何转换np.uint64。而在Python 2中,你有

>>> isinstance(np.uint64(12345).astype(int), int)
True

所以ctypes只是把它当作一个int

进一步generic.astype()的文档读

未实现(虚拟属性)

类generic的存在仅仅是为了从narray类派生numpy标量,并且拥有(尽管未实现)narray类的所有属性,从而提供统一的API。

和我不知道,为什么它在Python 2中工作。

相反,您可以使用int()np.uint64转换为可以强制转换为ctypes.c_void_p的内容。这在我的两个版本中都有效。

c_arr = C.cast(int(c_arrptr), dtype_ptr_t)

最新更新