Python 如何将ctypes C指针转换为Numpy数组?

Python 如何将ctypes C指针转换为Numpy数组?,python,numpy,ctypes,Python,Numpy,Ctypes,我正在用Python编写一个回调函数: @ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, np.ctypeslib.ndpointer(dtype=ctypes.c_ushort)) def FastModeCallback(hCam, x, y, w, h, binx, biny, imageBuffe

我正在用Python编写一个回调函数:

@ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, np.ctypeslib.ndpointer(dtype=ctypes.c_ushort))
def FastModeCallback(hCam, x, y, w, h, binx, biny, imageBuffer_ptr):

    image = np.ctypeslib.as_array(imageBuffer_ptr, shape=(h, w))
如何将
imageBuffer\u ptr
转换为
shape=(h,w)
dtype=c.ushort
的Numpy数组

我读到这个答案:

答案是:

两者都建议使用
np.ctypeslib.as_数组
,但当我尝试使用它时,会出现以下错误:

Exception ignored on calling ctypes callback function: <function FastModeCallback at 0x00000224E2992DC0>
Traceback (most recent call last):
  File "C:\Users\Dave\data\Code\Python\Cheese\atik.py", line 472, in FastModeCallback
    image = np.ctypeslib.as_array(imageBuffer_ptr, shape=(h, w))
  File "C:\Program_Files\anaconda3\lib\site-packages\numpy\ctypeslib.py", line 521, in as_array
    return array(obj, copy=False)
ValueError: '<P' is not a valid PEP 3118 buffer format string
调用ctypes回调函数时忽略异常: 回溯(最近一次呼叫最后一次): 文件“C:\Users\Dave\data\Code\Python\Cheese\atik.py”,第472行,在FastModeCallback中 image=np.ctypeslib.as_数组(imageBuffer_ptr,shape=(h,w)) 文件“C:\Program\u Files\anaconda3\lib\site packages\numpy\ctypeslib.py”,第521行,在as\U数组中 返回数组(obj,copy=False) ValueError:“正在列出和。后者陈述了以下两项内容(强调是我的):

  • as_阵列

    从ctypes数组或指针创建numpy数组。

  • ndpointer

    ndpointer实例用于描述RESTTYPE和argtypes规范中的ndarray。这种方法比使用指针(c\u double)更灵活,因为可以指定几个限制,这些限制在调用ctypes函数时进行验证

  • imageBuffer\u ptr不是一个“ctypes数组或指针”(字面意思是:它不是一个ctypes.POINTER实例,而是ctypes.c\u void\u p一个(两者之间有细微的区别))

    C层(在我们的例子中位于中间)不知道NumPy数组等等,所以从它的PoV来看,该参数只是一个无符号短*(没有关于形状的信息,…)。因此,在另一方面(在Python回调中),您必须从普通C指针重构数组。这可以通过两种方式实现,就像我在下面的示例中所做的那样:

    • 回调\u-ct:使用好的旧C方式:修改回调的签名以使用ct.POINTER(ct.C\u-short)。这是最简单的,但缺点是调用时会丢失所有额外的检查,这意味着它接受任何指针,而不仅仅是一个数组指针

    • 回调\u np:从参数手动重新创建数组(使用一系列转换)。它更先进(有些人甚至认为它有点讨厌)

    代码00.py:

    #/usr/bin/env python
    导入系统
    将ctypes导入为ct
    将numpy作为np导入
    基础=ct.c\U ushort
    NpPtr=np.ctypeslib.ndpointer(
    dtype=基本类型,
    flags='C_contracting',
    #ndim=1,
    )
    CtPtr=ct.指针(基本)
    @ct.CFUNCTYPE(无,ct.c_int,ct.c_int,NpPtr)
    def回调_np(宽、高、数据):
    打印(“\n回调\u np:”)
    #打印(数据,类型(数据),类型(数据)。\uuuuMRO\uuuuuuuuux,十六进制(数据值))
    #打印(数据.\n打印,数据.\u数据类型,数据.\u形状,数据.\u类型,数据.\u对象)
    img=np.ctypeslib.as_数组(ct.POINTER(Base).from_地址(ct.addressof(data)),shape=(h,w))
    #img=np.ctypeslib.as_数组(数据,形状=(h,w))#原始形式
    打印(img)
    @ct.CFUNCTYPE(无,ct.c_int,ct.c_int,CtPtr)
    def回调_ct(宽、高、数据):
    打印(“\n回调\u ct:”)
    img=np.ctypeslib.as_数组(数据,形状=(h,w))
    打印(img)
    def主(*argv):
    w=2
    h=3
    arr=np.数组(范围(h*w),dtype=Base)
    打印(“数组参数:”,arr,type(arr),arr.shape,arr.dtype,arr.ndim)
    回调类型(w,h,np.ctypeslib.as_ctypes(arr))
    回调_np(w,h,arr)
    如果名称=“\uuuuu main\uuuuuuuu”:
    打印(“Python{0:s}{1:d}位在{2:s}\n.format(“.”join(sys.version.split(“\n”)中的elem的elem.strip()),如果sys.maxsize>0x100000000,则为64,否则为32,sys.platform))
    rc=main(*sys.argv[1:]
    打印(“\n完成”)
    系统出口(rc)
    
    输出

    [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q067323177]>“e:\Work\Dev\VEnvs\py\u pc064\u 03.08.07\u test0\Scripts\python.exe”code00.py
    win32上的Python 3.8.7(tags/v3.8.7:6503f052020年12月21日17:59:51)[MSC v.1928 64位(AMD64)]64位
    数组参数:[0 1 2 3 4 5](6,)uint16 1
    回拨时间:
    [[0 1]
    [2 3]
    [4 5]]
    回调\u np:
    [[0 1]
    [2 3]
    [4 5]]
    完成。
    

    可能会有帮助。还有,你是如何调用函数的?你传递给它的参数是什么?@CristiFati它是一个第三方DLL;我没有消息来源,也不知道它叫什么。