Python ctypes 复制结构位于临时缓冲区中

问题描述 投票:0回答:1

我有一个如下所示的代码:

from ctypes import *
import some_library

class Thing(Structure):
    _fields_ = [
        ("A", c_uint8*4),
        ("B", Group*4)]

pointer_to_thing = POINTER(Thing)()

def get_thing():
    some_library.allocate_memory_for_thing()
    some_library.read_thing()
    pointer_to_thing = some_library.give_me_the_thing()
    thing = pointer_to_thing.contents
    some_library.release_memory()
    return thing

thing = get_thing()

失败了,因为

some_library.give_me_the_thing()
给了我对该事物的引用,而
some_library.release_memory()
正在释放该事物所在的内存。如果我评论
some_library.release_memory()
它可以工作,但这不是它应该如何完成的。我必须在从函数返回之前释放内存,因此我想复制该内容并返回该副本,如下所示:

def get_thing():
    some_library.allocate_memory_for_thing()
    some_library.read_thing()
    pointer_to_thing = some_library.give_me_the_thing()
    thing = pointer_to_thing.contents
    copy_of_thing = Thing()
    memmove(
        addressof(copy_of_thing),
        addressof(thing),
        sizeof(Thing),
    )
    some_library.release_memory()
    return copy_of_thing

但是,它总是返回不正确数据的

Thing
。如果
some_library.release_memory()
被注释,那么它会按预期工作。就好像根本没有复制内容一样……

我也尝试过

def get_thing():
    some_library.allocate_memory_for_thing()
    some_library.read_thing()
    pointer_to_thing = some_library.give_me_the_thing()
    thing = pointer_to_thing.contents
    copy_of_thing = Thing.copy_from_buffer(thing)
    some_library.release_memory()
    return copy_of_thing

行为是完全相同的,即如果我释放内存,它就会失败,如果我不释放它,它就会工作。

不幸的是

some_library
是一件复杂的事情,我无法轻松创建一个MWE来发布在这里。

python copy ctypes
1个回答
0
投票

只要您的对象是连续内存并且不包含指向其他已分配内存的指针,

.from_buffer_copy()
就应该可以工作。一个简单的演示:

import ctypes as ct


crt = ct.CDLL('msvcrt')
crt.malloc.argtypes = ct.c_size_t,
crt.malloc.restype = ct.c_void_p
crt.free.argtypes = ct.c_void_p,
crt.free.restype = None

class Thing(ct.Structure):
    _fields_ = (('a', ct.c_uint8 * 4),
                ('b', ct.c_uint8 * 4))
    def __repr__(self):
        return f'Thing(a={bytes(self.a)}, b={bytes(self.b)})'

# A "C" malloc and init of some memory and
# build a thing simulating returning a
# malloc-ed object from C
s = crt.malloc(8)
ct.memmove(s, b'1234abcd', 8)
thing1 = Thing.from_address(s)

thing2 = Thing.from_buffer(thing1)      # references existing memory
thing3 = Thing.from_buffer_copy(thing1) # makes a copy

# fill the memory with a deleted pattern, then free it.
ct.memmove(s, b'\xdd' * 8, 8)
crt.free(s)

print(thing2)
print(thing3)

输出:

Thing(a=b'\xdd\xdd\xdd\xdd', b=b'\xdd\xdd\xdd\xdd')
Thing(a=b'1234', b=b'abcd')
© www.soinside.com 2019 - 2024. All rights reserved.