【发布时间】:2015-09-25 05:36:10
【问题描述】:
我遇到了一个问题,我的 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
形状 - (506, 6) - 元组
arr_t - numpy.ctypeslib.ndpointer_
dtype - np.float32 - np.float32
这些在python2和python3版本之间是一样的(当然除了指针的值,但还是uint64)
当我执行该函数时,它在 python2 中按预期工作。 但是,在 python3 中,我在这一行出现错误
c_arr = C.cast(typed_c_arrptr, dtype_ptr_t) # cast to ctypes
错误是 ArgumentError
/usr/lib/python3.4/ctypes/__init__.py in cast(obj, typ)
487 def cast(obj, typ):
--> 488 return _cast(obj, obj, typ)
489
ArgumentError: argument 1: <class 'TypeError'>: wrong type
During handling of the above exception, another exception occurred:
ArgumentError Traceback (most recent call last)
in <module>()
----> 1 c_arr = C.cast(typed_c_arrptr, dtype_ptr_t) # cast to ctypes
/usr/lib/python3.4/ctypes/__init__.py in cast(obj, typ)
486 _cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
487 def cast(obj, typ):
--> 488 return _cast(obj, obj, typ)
489
490 _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
ArgumentError: argument 1: <class 'TypeError'>: wrong type
在代码执行的那一点上,typed_c_arrptr 在程序的两个版本中都是一个 dtype('int64')。 dtype_ptr_t 是一个 LP_c_char_Array_4 也在两个版本中。
我尝试了许多关于 typed_c_arrptr = c_arrptr.astype(int) 的变体,将 int 替换为 ctypes.c_int、ctypes.c_long、ctypes.c_size_t。在这一点上,我只是在猜测要做什么以及出了什么问题。对此的任何帮助将不胜感激。
【问题讨论】:
-
如果在每个版本中将
int替换为long会发生什么? -
long 在 python3 中不作为关键字存在,在 python 2 中它不起作用。我也尝试过使用 ctypes.c_long。
-
我没有 Python 3,但据我所知,
int与 Python 2 的大小不同。long的大小与 Python 2 中的int不同,并且这似乎也导致您的代码失败。可能是一个提示。 -
我知道这种差异,但这似乎不是问题。也许应该更改 ctypes.c_int32 或类似的东西,但即使发生这种情况,问题仍然存在。