Python ctypes:复制结构体的内容 [英] Python ctypes: copying Structure's contents

查看:661
本文介绍了Python ctypes:复制结构体的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用ctypes模拟Python中的一段C代码,代码如下:

  typedef struct { 
int x;
int y;
} point;

void copy_point(point * a,point * b){
* a = * b;
}

在ctypes中不能执行以下操作:

 来自ctypes import * 

类Point(Structure):
_fields_ = [(x,c_int) ,(y,c_int)]

def copy_point(a,b):
a.contents = b.contents

p0 = ))
p1 = pointer(Point())
copy_point(p0,p1)

因为 contents 仍然是一个Python ctypes Structure对象,它作为一个引用本身进行管理。



一个明显的解决方法是手动复制每个字段(表示为不可变的python int),但不能扩展更复杂的结构。



我的另一个选择是使用 memmove code>并复制对象,就像它们是缓冲区一样,但是这似乎很容易出错(因为Python是动态类型化的,所以对于不同类型和大小的对象使用它会导致内存损坏或分段错误)...



有任何建议吗?





我还可以使用新的结构副本,所以也许这是有用的:

  import copy 
p0 = Point()
p1 = copy.deepcopy(p0)#这个例子只是一个浅拷贝

但我不知道是否可能有某种奇怪的行为复制ctypes proxys,就像他们是普通的Python对象...

解决方案

您可以使用序列分配来复制指向的对象(而不是分配到 p.contents ,它改变了指针的值):

  def copy(dst,src):
内容src to dst
指针(dst)[0] = src

#交替
def new_copy(src):
新的ctypes对象,它是一个现有的一个按位复制
dst = type(src)()
指针(dst)[0] = src
return dst

#或如果使用指针
def ptr_copy(dst_ptr,src_ptr):
dst_ptr [0] = src_ptr [0]

ctypes 会为你做类型检查(这不是傻瓜,但是比没有更好) / p>

使用示例,验证其确实可以正常工作):

 >>>> o1 = Point(1,1)
>>>> o2 = Point(2,2)
>>>> print(o1.x,o1.y,addressof(o1)),(o2.x,o2.y,addressof(o2))
(1,1,6774004)(2,2,6473524)
>>>> copy(o2,o1)
>>> pprint(o1.x,o1.y,addressof(o1)),(o2.x,o2.y,addressof(o2))
(1,1,6774004)(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 =指针(o1),指针(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)


I want to mimic a piece of C code in Python with ctypes, the code is something like:

typedef struct {
  int x;
  int y;
} point;

void copy_point(point *a, point *b) {
  *a = *b;
}

in ctypes it's not possible to do the following:

from ctypes import *

class Point(Structure):
  _fields_ = [("x", c_int),("y", c_int)]

def copy_point(a, b):
  a.contents = b.contents

p0 = pointer(Point())
p1 = pointer(Point())
copy_point(p0,p1)

as the contents still is a Python ctypes Structure object, that is managed as a reference itself.

An obvious workaround would be to manually copy each field (that is represented as immutable python int's), but that doesn't scale with more complex structures. Also, it would need to be done recursively for fields that are not basic, but structured types.

My other option is to use memmove and copy the objects as if they were buffers, but that seems very error prone (as Python is dynamically typed it would be too easy to use it with objects of distinct type and size, leading to memory corruption or segmentation faults)...

Any suggestions?

Edit:

I could also use a fresh new copy of the structure, so maybe this could be useful:

import copy
p0 = Point()
p1 = copy.deepcopy(p0) #or just a shallow copy for this example

but I don't know if there might be some kind of bizarre behaviours copying ctypes proxys as if they were regular Python objects...

解决方案

You can use sequence assignment to copy the pointed-to objects (rather than assigning to p.contents, which changes the pointer value):

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 will do type checking for you (which isn't fool-proof, but it's better than nothing).

Example of use, with verification that it does in fact work ;):

>>> 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)

这篇关于Python ctypes:复制结构体的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆