有很多示例显示如何将单个变量甚至单个结构成员写入共享内存,但有没有办法将整个结构放入共享内存,以便您可以简单地操作结构来更新共享内存?
这是我到目前为止所做的一个例子(在我的实际程序中 - 结构中有超过50个字段 - 当我完成时可能有100多个字段)。它每隔0.05秒用x,y,z坐标更新共享内存。虽然它可以正常工作,但它在每一步都会打包一个新结构,并将整个内容写入共享内存 - 这对我来说似乎效率低下。
import mmap
import struct
import ctypes
import time
import random
class GenericData(ctypes.Structure):
_pack_ = 4
_fields_ = [
('PosX', ctypes.c_float),
('PosY', ctypes.c_float),
('PosZ', ctypes.c_float),
]
# fake getters:
def getX():
return random.random()*10
getZ = getY = getX
def main():
buff = mmap.mmap(0, ctypes.sizeof(GenericData), "$MyTag$")
data = GenericData()
fmt = ''.join([f[1]._type_ for f in data._fields_])
while (1):
data.PosX = getX()
data.PosY = getY()
data.PosZ = getZ()
print "Setting %f, %f, %f " % (data.PosX, data.PosY, data.PosZ)
struct.pack_into(fmt, buff, 0, *[getattr(data,field) for field,typ in data._fields_])
time.sleep(0.05)
if __name__ == "__main__":
main()
我知道我可以创建变量到共享内存文件中位置的映射,但是有这么多字段,这有点笨拙。
我想结构可以是缓冲区(或映射到缓冲区),只需设置data.PosX,就可以更新共享内存。这可能吗?有没有办法让这个更有效率? struct.pack_into行与我有关。
我想这样的事情可以做到:
buff = mmap.mmap(0, ctypes.sizeof(GenericData), "$MyTag$")
data = from_buffer(buff, GenericData)
while (1):
data.posX = getX()
data.posY = getY()
data.posZ = getZ()
time.sleep(0.05)
...然后会更新共享内存。可能的?
答案 0 :(得分:1)
正如@eryksun在问题的第一条评论中指出的那样,您可以使用ctypes.from_buffer
与mmap缓冲区GenericData
共享ctypes结构buff
。 @eryksun还指出,虽然Windows允许0
作为文件描述符来映射匿名内存,但-1
是正确的值 - 如文档中所述。
有了这个,这是一个有效的例子,调整为包括@ eryksun的答案:
import ctypes
import mmap
import time
import math
class GenericData(ctypes.Structure):
_pack_ = 4
_fields_ = [
('PosX', ctypes.c_float),
('PosY', ctypes.c_float),
('PosZ', ctypes.c_float),
]
# fake getters:
def getX():
return random.random()*10
getZ = getY = getX
def main():
buff = mmap.mmap(-1, ctypes.sizeof(GenericData), "$MyTag$")
data = GenericData.from_buffer(buff)
for fname, ftype in data._fields_:
setattr(data, fname, 0)
count = 0
while (1):
data.PosX = getX()
data.PosY = getY()
data.PosZ = getZ()
print ("Setting %f, %f, %f " % (data.PosX, data.PosY, data.PosZ))
count += 1
time.sleep(0.05)
if __name__ == "__main__":
main()