在多个平台上通过python进程同步由ctypes指针表示的内存

时间:2017-11-04 10:42:10

标签: python python-3.x serialization ctypes python-multiprocessing

我正在运行两个Python 3解释器,一个在Linux上,另一个在Windows系统上。他们使用multiprocessing.connectionClientListener)进行通信(即交换数据)。在这两者之间,我必须保持ctypes指针所代表的任意数据结构的内容同步。

问题是我需要有效地来回传送数据的内容。 multiprocessing.connectionpickle发送任何数据,因此我必须将数据序列化为可以腌制的数据。

到目前为止,我将内存中的每个字节序列转换为Python整数的Python列表。嗯,它(至少)有效......

def generate_pointer_from_int_list(int_array):

    return ctypes.pointer((ctypes.c_ubyte * len(int_array))(*int_array))


def overwrite_pointer_with_int_list(ctypes_pointer, int_array):

    (ctypes.c_ubyte * len(int_array)).from_address(ctypes.c_void_p.from_buffer(ctypes_pointer).value)[:] = int_array[:]


def serialize_pointer_into_int_list(ctypes_pointer, size_bytes):

    return (ctypes.c_ubyte * size_bytes).from_address(ctypes.c_void_p.from_buffer(ctypes_pointer).value)[:]

我想知道是否有办法提高效率(就需要转移的数据量和速度而言,自然而然)。

我的一个想法是使用Python字节串而不是整数列表,这将减少所需的内存量。但是,我没有设法让它发挥作用。我怎么能改变上面的例程?

我还有什么其他的,可能更好/更快/更节省内存的选项?

serialize_pointer_into_int_list的使用示例:

sample_len = 5
sample_p = ctypes.pointer((ctypes.c_double * sample_len)(1.0, 2.0, 3.0, 4.0, 5.0))
sample_int_list = serialize_pointer_into_int_list(sample_p, sample_len * ctypes.sizeof(ctypes.c_double))
print(sample_int_list)
print(type(sample_int_list))

输出:

[0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 16, 64, 0, 0, 0, 0, 0, 0, 20, 64]
<class 'list'>

1 个答案:

答案 0 :(得分:1)

假设每个数据部分都不是那么大(因为解决方案需要复制),可以这样做(在交互式shell中显示):

>>> import pickle
>>> import ctypes
>>> b = (ctypes.c_double * 5)(1.0, 2.0, 3.0, 4.0, 5.0)  # Arbitrary data
>>> d = pickle.dumps(bytes(b))
>>> c = pickle.loads(d)
>>> a = (ctypes.c_double * 5).from_buffer_copy(c)
>>> a
<__main__.c_double_Array_5 object at 0x02F6C9E0>
>>> list(a)
[1.0, 2.0, 3.0, 4.0, 5.0]