Python ctypes: копирование содержания Структуры

JasperReports, если Вы пишете Java.

9
задан fortran 24 September 2009 в 08:44
поделиться

4 ответа

Вы можете использовать назначение последовательности для копирования указанных объектов (вместо присвоения p.contents , которое изменяет значение указателя):

def copy(dst, src):
    """Copies the contents of src to dst"""
    pointer(dst)[0] = src

# alternately
def new_copy(src):
    """Returns a new ctypes object which is a bitwise copy of an existing one"""
    dst = type(src)()
    pointer(dst)[0] = src
    return dst

# or if using pointers
def ptr_copy(dst_ptr, src_ptr):
    dst_ptr[0] = src_ptr[0]

ctypes выполнит проверку типов за вас (что не является надежным, но лучше, чем ничего).

Пример использования с проверкой того, что это действительно работает ;):

>>> o1 = Point(1, 1)
>>> o2 = Point(2, 2)
>>> print (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2))
(1, 1, 6474004) (2, 2, 6473524)
>>> copy(o2, o1)
>>> pprint (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2))
(1, 1, 6474004) (1, 1, 6473524)

>>> o1 = Point(1, 1), o2 = Point(2, 2)
>>> print (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2))
(1, 1, 6473844) (2, 2, 6473684)
>>> p1, p2 = pointer(o1), pointer(o2)
>>> addressof(p1.contents), addressof(p2.contents)
(6473844, 6473684)
>>> ptr_copy(p1, p2)
>>> print (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2))
(2, 2, 6473844) (2, 2, 6473684)
>>> addressof(p1.contents), addressof(p2.contents)
(6473844, 6473684)
6
ответ дан 4 December 2019 в 19:35
поделиться

memmove здесь правильная операция. Установив argtypes вашей функции CopyPoint, вы можете легко обеспечить безопасность типов.

from ctypes import *

class Point(Structure):
    _fields_ = [("x", c_int), ("y", c_int)]
    def __str__(self):
        return "<Point: x=%d, y=%d, addr=%ld>" % (self.x, self.y, addressof(self))

def CopyPoint(a, b):
    memmove(a, b, sizeof(Point))
CopyPoint.argtypes = [POINTER(Point), POINTER(Point)]

pt0 = Point(x=0, y=10)
pt1 = Point(x=5, y=7)

print pt0, pt1

CopyPoint(byref(pt0), byref(pt1))
print pt0, pt1    

try:
    CopyPoint(byref(pt0), Point(x=2, y=3))
except ArgumentError as e:
    print "Could not copy!", e

output:

$ python ct.py 
<Point: x=0, y=10, addr=3083711192> <Point: x=5, y=7, addr=3083711120>
<Point: x=5, y=7, addr=3083711192> <Point: x=5, y=7, addr=3083711120>
Could not copy! argument 2: <type 'exceptions.TypeError'>: wrong type

Обратите внимание, что вы можете легко создать фабрику для генерации такого типа функции во время выполнения. для определенного типа, если вам нужно обобщить:

def CopierFactory(typ):
    def f(a,b):
        memmove(a,b, sizeof(typ))
    f.argtypes = [POINTER(typ), POINTER(typ)]

    return f

copy_point = CopierFactory(Point)

a = Point(x=1, y=2)
b = Point(x=-1, y=-1)
print a, b
copy_point(byref(a), byref(b))
print a, b

output:

<Point: x=1, y=2, addr=3085088024> <Point: x=-1, y=-1, addr=3085087952>
<Point: x=-1, y=-1, addr=3085088024> <Point: x=-1, y=-1, addr=3085087952>
6
ответ дан 4 December 2019 в 19:35
поделиться

Сейчас я также думаю об определении такого метода, как:

def safe_copy(dst, src):
  if type(src) != type(dst) or not isinstance(src, Structure):
    raise Exception("wrong types")
  memmove(addressof(dst), addressof(src), sizeof(src))

Но может быть есть еще более приятные варианты ...

0
ответ дан 4 December 2019 в 19:35
поделиться

Операции с указателями, как правило, не очень безопасны для памяти. Я бы создал классы-оболочки для каждого интересующего вас типа данных структуры и позволил бы им обрабатывать операции копирования указателя. Примерно так же, как вы делаете здесь. Существуют лямбда-функции и функции отображения, которые можно рекурсивно использовать в качестве синтаксического сахара.

0
ответ дан 4 December 2019 в 19:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: