从QSharedMemory复制列表到sip.voidptr的Python方法

时间:2018-07-04 08:55:25

标签: python pyqt pyqt5 qsharedmemory

我正在使用PyQT5和QSharedMemory类。我正在创建一个可以容纳6个1字节元素的共享内存。为了将这些要素复制到共享内存阵列中,我正在遍历python列表中的要素,如以下代码片段所示:

f = shared_mem.data()
k = f.asarray()
memtocopy = [0,1,2,3,4,5]
for i in range(0,len(memtocopy)):
    k[i]  = memtocopy[i]
shared_mem.unlock()

这似乎非常不符合Python和样板代码。我想知道是否有更合适的方法来达到相同的结果?

使用时

k[:] = memtocopy

或:

k[:] = np.asarray(memtocopy,np.uint8)

它将失败,并显示错误消息:

TypeError: can only assign another array of unsigned char to the slice

用于再现的整个测试代码如下:

from PyQt5 import QtCore 

# Create shared memory and attach it
shared_mem = QtCore.QSharedMemory()
shared_mem.setNativeKey("test")
shared_mem.create(4*6)
shared_mem.attach()


# Fill in 
shared_mem.lock()
f = shared_mem.data()
k = f.asarray()

memtocopy = [0,1,2,3,4,5]

# Loop in question
for i in range(0,len(memtocopy)):
    k[i]  = memtocopy[i]

shared_mem.unlock()



# Read out
shared_mem.lock()
f1 = shared_mem.data()
k1 = f1.asarray()
shared_mem.unlock()

# Test results
if k1[0] == memtocopy[0]:
    print("success!")
else:
    print("fail!")

2 个答案:

答案 0 :(得分:1)

经过一番摆弄之后,我设法产生了一种对我有用的组合:

a = array.array('i', range(6))
f[:] = buffer(a)
b = array.array('i')
b.fromstring(buffer(f))

这依赖于缓冲区协议来双向读取。您可能可以直接将数组与k一起使用,并且fromstring在更高版本中已重命名为frombytes

在Python 3.4中,此方法有效:

a = array.array('i', range(6))
f[:] = memoryview(a).cast('B')
b = array.array('i')
b.frombytes(memoryview(f))

memoryview替换了buffer,但是知道元素长4个字节,因此需要额外的转换。

答案 1 :(得分:1)

这是使用structmemoryview的一种更简单的方法,它使用一对单线来读取和写入数据 :

import struct
from PyQt5 import QtCore

shared_mem = QtCore.QSharedMemory()
shared_mem.setNativeKey("test")
shared_mem.create(4*6)
shared_mem.attach()

memtocopy = [0,1,2,3,4,5]

try:

    # Fill in 
    shared_mem.lock()
    shared_mem.data()[:] = memoryview(struct.pack('=6i', *memtocopy))
    shared_mem.unlock()

    # Read out
    shared_mem.lock()
    # python3
    k = memoryview(shared_mem.data()).cast('i')
    # python2
    # k = struct.unpack('=6i', memoryview(shared_mem.data()))
    shared_mem.unlock()

    if k[3] == memtocopy[3]:
        print("success!")
    else:
        print("fail!")

finally:

    shared_mem.detach()