ArgumentError:预期的LP_c_float实例,而不是指向LP_c_float_Array_50000的指针

时间:2019-03-19 07:00:12

标签: python ctypes

我在dll文件中有一个函数,该函数将float指针作为参数之一(参数9:float * result)。

void generate_codebook(int *nodestatus, int *nofnode, int *noftree, int *terminal,  int *nofterminal, int *nofobservations, int *total, int *nofseries,  float *result)

这是我面临问题的python代码:

nofseries=c_int(len(nofobservations))
noftree=c_int(terminal.shape[1])
nofnode=c_int(nodestatus.shape[0])
total=c_int(np.sum(nofobservations,dtype=np.int64))
nofentry=ctypes.POINTER(ctypes.c_float *(len(nofobservations)*nofterminal*terminal.shape[1]))()
mydll.generate_codebook.argtypes = [POINTER(c_int), POINTER(c_int), POINTER(c_int), POINTER(c_int),
                                  POINTER(c_int), POINTER(c_int), POINTER(c_int), POINTER(c_int), POINTER(c_float)]
result=mydll.generate_codebook(nodestatus.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),
                               nofnode,noftree,terminal.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),
                               c_int(nofterminal),
                               nofobservations.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),total,
                               nofseries,
                              ctypes.byref(nofentry))

在调用generate_codebook函数时,我在最后一个需要LP_c_float实例的参数中遇到参数错误。错误如下:

<ipython-input-28-f73a7383211e> in generatecodebook(nodestatus, terminal, nofterminal, nofobservations)
 16                                    nofobservations.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),total,
 17                                    nofseries,
---> 18                                   ctypes.byref(nofentry))

ArgumentError: argument 9: <class 'TypeError'>: expected LP_c_float instance instead of pointer to LP_c_float_Array_50000

我经历了this问题的解决方案,但无法解决错误。 预先谢谢你!

1 个答案:

答案 0 :(得分:0)

您的 nofentry 值是指向 float 数组的指针,而 generate_codebook 则需要指向 float 的指针>。 ctypes 无法自动进行这种转换,因此必须手动执行(使用[Python 3]: ctypes.cast(obj, type))。

示例:

>>> import ctypes
>>>
>>> dim = 100
>>>
>>> FloatArr100 = ctypes.c_float * dim
>>> FloatArr100Ptr = ctypes.POINTER(FloatArr100)
>>>
>>> float_arr = FloatArr100(*range(dim))
>>> float_arr[4], float_arr[38], float_arr[99]
(4.0, 38.0, 99.0)
>>>
>>> float_arr_ptr = ctypes.pointer(float_arr)  # This is the equivalent of your `nofentry`
>>> float_arr_ptr
<__main__.LP_c_float_Array_100 object at 0x000001921ED85A48>
>>> type(float_arr_ptr) is FloatArr100Ptr
True
>>>
>>> float_ptr = ctypes.cast(float_arr, ctypes.POINTER(ctypes.c_float))  # This is what you should do
>>>
>>> float_ptr
<__main__.LP_c_float object at 0x000001921ED859C8>
>>> float_ptr[4], float_ptr[38], float_ptr[99]
(4.0, 38.0, 99.0)

已翻译为您的代码:

  1. 国防的定义更改为:

    nofentry = (ctypes.c_float * (len(nofobservations) * nofterminal * terminal.shape[1]))()  # Notice dropping `ctypes.POINTER`
    
  2. 调用mydll.generate_codebook时,替换

    ctypes.byref(nofentry)
    

    使用

    ctypes.cast(nofentry, ctypes.POINTER(ctypes.c_float))
    

    所以最后它看起来像:

    result = mydll.generate_codebook(nodestatus.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),
                                     nofnode, noftree, terminal.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),
                                     c_int(nofterminal),
                                     nofobservations.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),
                                     total, nofseries,
                                     ctypes.cast(nofentry, ctypes.POINTER(ctypes.c_float)))