Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python3 memoryview对象到C函数char*参数_Python_Qt_Ctypes_Pyside2 - Fatal编程技术网

python3 memoryview对象到C函数char*参数

python3 memoryview对象到C函数char*参数,python,qt,ctypes,pyside2,Python,Qt,Ctypes,Pyside2,帧如下:PySide2允许我使用bits()-调用访问内部像素数据。该调用返回memoryview-object,我希望将其传递给C库函数,该函数对图像像素数据进行处理(例如,它执行超级奇妙的模糊) 问题是,我还并没有找到一种方法将memoryview参考底图数据作为ctypes调用参数 也就是说:如何从memoryview对象ctypes.c\u void\u p(或类似)中获取数据,而不复制缓冲区。memoryviewtobytes()返回字节,但它从内存中复制,因此修改它不会修改原始图像(

帧如下:PySide2允许我使用
bits()
-调用访问内部像素数据。该调用返回memoryview-object,我希望将其传递给C库函数,该函数对图像像素数据进行处理(例如,它执行超级奇妙的模糊)

问题是,我还并没有找到一种方法将memoryview参考底图数据作为ctypes调用参数

也就是说:如何从memoryview对象
ctypes.c\u void\u p
(或类似)中获取数据,而不复制缓冲区。memoryview
tobytes()
返回字节,但它从内存中复制,因此修改它不会修改原始图像(像素数据)

现在,python
silly.py
方面的最小示例是:

import ctypes
from PySide2.QtGui import QImage

img = QImage(500,100, QImage.Format.Format_RGB32 )
data = img.bits()
print(data)

dll = ctypes.CDLL( "./silly.o" )
dll_set_image = getattr( dll, "set_image" )
dll_set_image.argtypes = [ ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32 ]
# Next line gives: ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type
dll_set_image( data, img.width(), img.height() ) 
编译和测试:

% gcc -shared -o silly.o silly.c
% python3 silly.py              
<memory at 0x7f2f9806a700>
Traceback (most recent call last):
  File "silly.py", line 13, in <module>
    dll_set_image( data, img.width(), img.height() ) 
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

python setup.py build_ext --inplace
python main.py
%gcc-shared-o傻瓜.o傻瓜.c
%python3.py
回溯(最近一次呼叫最后一次):
文件“dully.py”,第13行,在
dll\u设置\u图像(数据,img.width(),img.height())
ctypes.ArgumentError:参数1::错误类型
不是一个void*而是一个结构(),它的成员中是缓冲区,因此转换不是直接的

在这些情况下,我更喜欢使用Cython(
python-mpipinstallcython
),它允许以简单的方式创建库的包装器。考虑到上述情况,我创建了一个项目:

├── main.py
├── psilly.c
├── psilly.pyx
├── setup.py
├── silly.c
├── silly.h
└── silly.pxd
愚蠢的.h

extern void set_image( unsigned char* data, uint32_t xsize, uint32_t ysize, uint32_t channels);
愚蠢的.c

#包括
#包括“愚蠢的.h”
无效集图像(无符号字符*数据、uint32大小、uint32大小、uint32大小、uint32通道)
{
//填充白色
对于(uint32_t i=0;i<(xsize*ysize*通道);i++)
{
数据[i]=255;
}
}
愚蠢的.pxd

from libc.stdint cimport uint32_t

cdef extern from "silly.h":  
    void set_image(unsigned char* data, uint32_t xsize, uint32_t ysize, uint32_t channels)
psilly.pyx

cimport silly

cpdef set_image(unsigned char[:] data, int width, int height, int channels):
    silly.set_image(&data[0], width, height, channels)
setup.py

来自distutils.core导入扩展,设置
从Cython.Build导入cythonize
ext=分机(
name=“psilly”,
sources=[“psilly.pyx”,“silly.c”],
)
设置(ext_模块=cythonize(ext))
main.py

import psilly
从PySide2.qtwidts导入QApplication、QHBoxLayout、QLabel、QWidget
从PySide2.QtGui导入QImage、QPixmap
app=QApplication()
img=QImage(500100,QImage.Format.Format_RGB32)
数据=img.bits()
label1=QLabel()
label1.setPixmap(QPixmap.fromImage(img.copy()))
psilly.set_图像(数据,img.width(),img.height(),4)
label2=QLabel()
label2.setPixmap(QPixmap.fromImage(img))
widget=QWidget()
lay=QHBoxLayout(小部件)
lay.addWidget(标签1)
lay.addWidget(label2)
widget.show()
app.exec()
编译和测试:

% gcc -shared -o silly.o silly.c
% python3 silly.py              
<memory at 0x7f2f9806a700>
Traceback (most recent call last):
  File "silly.py", line 13, in <module>
    dll_set_image( data, img.width(), img.height() ) 
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

python setup.py build_ext --inplace
python main.py
输出:

注意:在编译项目时,它是作为PSILY.c的中间元素生成的,在PSILY.c中,您将看到使用Py_缓冲区结构在memoryview和
unsigned char*
之间的转换。

不是一个void*而是一个结构(),其成员中是缓冲区,因此转换不是直接的

在这些情况下,我更喜欢使用Cython(
python-mpipinstallcython
),它允许以简单的方式创建库的包装器。考虑到上述情况,我创建了一个项目:

├── main.py
├── psilly.c
├── psilly.pyx
├── setup.py
├── silly.c
├── silly.h
└── silly.pxd
愚蠢的.h

extern void set_image( unsigned char* data, uint32_t xsize, uint32_t ysize, uint32_t channels);
愚蠢的.c

#包括
#包括“愚蠢的.h”
无效集图像(无符号字符*数据、uint32大小、uint32大小、uint32大小、uint32通道)
{
//填充白色
对于(uint32_t i=0;i<(xsize*ysize*通道);i++)
{
数据[i]=255;
}
}
愚蠢的.pxd

from libc.stdint cimport uint32_t

cdef extern from "silly.h":  
    void set_image(unsigned char* data, uint32_t xsize, uint32_t ysize, uint32_t channels)
psilly.pyx

cimport silly

cpdef set_image(unsigned char[:] data, int width, int height, int channels):
    silly.set_image(&data[0], width, height, channels)
setup.py

来自distutils.core导入扩展,设置
从Cython.Build导入cythonize
ext=分机(
name=“psilly”,
sources=[“psilly.pyx”,“silly.c”],
)
设置(ext_模块=cythonize(ext))
main.py

import psilly
从PySide2.qtwidts导入QApplication、QHBoxLayout、QLabel、QWidget
从PySide2.QtGui导入QImage、QPixmap
app=QApplication()
img=QImage(500100,QImage.Format.Format_RGB32)
数据=img.bits()
label1=QLabel()
label1.setPixmap(QPixmap.fromImage(img.copy()))
psilly.set_图像(数据,img.width(),img.height(),4)
label2=QLabel()
label2.setPixmap(QPixmap.fromImage(img))
widget=QWidget()
lay=QHBoxLayout(小部件)
lay.addWidget(标签1)
lay.addWidget(label2)
widget.show()
app.exec()
编译和测试:

% gcc -shared -o silly.o silly.c
% python3 silly.py              
<memory at 0x7f2f9806a700>
Traceback (most recent call last):
  File "silly.py", line 13, in <module>
    dll_set_image( data, img.width(), img.height() ) 
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

python setup.py build_ext --inplace
python main.py
输出:


注意:在编译项目时,它将作为PSILY.c的中间元素生成,在PSILY.c中,您将看到使用Py_缓冲区结构在memoryview和
无符号字符*
之间的转换。

A
memoryview
支持Python缓冲区协议,因此,使用其
from\u buffer
方法创建一个大小合适的
ctypes
数组,该方法不会复制,而是引用相同的内存

稍微修改示例以查看缓冲区更改:

c:

#包括
#包括
#ifdef_WIN32
#定义API_uudeclspec(dllexport)
#否则
#定义API
#恩迪夫
API无效集图像(无符号字符*数据、uint32大小、uint32大小)
{
printf(“%p%u%u\n”,数据,xsize,ysize);
*数据=123;
}
test.py:

导入ctypes
从PySide2.QtGui导入QImage
img=QImage(500100,QImage.Format.Format_RGB32)
数据=img.bits()
打印('原件:',数据[0])
dll=ctypes.CDLL('./愚蠢')
dll\u set\u image=dll.set\u image
dll\u set\u image.argtypes=ctypes.c\u void\u p,ctypes.c\u uint32,ctypes.c\u uint32
缓冲区=(ctypes.c_ubyte*len(数据))。来自缓冲区(数据)
dll\u设置\u图像(缓冲区,img.width(),img.height())
打印('最终:',数据[0])
输出:

原件:80
00000213CF3C080 500 100
决赛:123

A
memoryview
支持Python缓冲区协议,因此使用其
from\u buffer
方法创建一个大小合适的
ctypes
数组,该方法不会创建副本,而是引用相同的内存

稍微修改示例以查看缓冲区更改:

c: