【问题标题】:ctypes: c_ulong type magically changed to longctypes: c_ulong 类型神奇地变成了 long
【发布时间】:2018-02-11 23:39:59
【问题描述】:

我正在为我的班级使用 python2.7 编写 deepcopy 函数。我遇到了一个奇怪的问题 我的代码如下

import copy
from ctypes import *
class Graph (Structure):
    _fields_ = [("numVertices", c_ulong),
                    ("numEdges", c_ulong)]
    def __init__(self):
        self.numVertices = c_ulong(0)
        self.numEdges = c_ulong(0)

    def __deepcopy__(self,memo={}):
        newInstance = Graph()
        newInstance.numVertices = c_ulong(self.numVertices.value)
        newInstance.numEdges = c_ulong(self.numEdges.value)
        return newInstance

graph = Graph()
anotherGraph = copy.deepcopy(graph)

我收到以下错误:

<ipython-input-46-a0cdaa4ef3f7> in __deepcopy__(self, memo)
      9     def __deepcopy__(self,memo={}):
     10         newInstance = Graph()
---> 11         newInstance.numVertices = c_ulong(self.numVertices.value)
     12         newInstance.numEdges = c_ulong(self.numEdges.value)
     13         return newInstance

AttributeError: 'long' object has no attribute 'value'

如果你尝试:

type(graph.numVertices)

结果很长

我将 numVertices 声明为 c_ulong()。为什么会变长?

【问题讨论】:

  • 我知道c_ulong的value属性的类型是long。但我的问题是,为什么 c_ulong 类型的字段会变成 long 类型。您会看到 numVertices 是 c_ulong 类型,它应该有一个 value 属性。但是在__deepcopy__ 函数中,它的类型变成了 long 而不是 c_ulong 并且它根本没有 'value' 属性!
  • 我明白你的意思。我删除了我的错误答案。有趣的是,从课程中删除 _fields_ 后,您会得到预期的结果。

标签: python ctypes


【解决方案1】:

结构中字段的类型仍然保持不变,但是 ctypes 在读取值时有一些“有用”的转换:

from ctypes import *

class Test(Structure):
    _fields_ = [('a',c_ulong),
                ('b',c_char_p)]

t = Test(1,b'hello')
print(type(t.a),type(t.b))
print(t._fields_)

输出:

<class 'int'> <class 'bytes'>
[('a', <class 'ctypes.c_ulong'>), ('b', <class 'ctypes.c_char_p'>)]

所以你可以编写如下代码,它会正常工作:

import copy
from ctypes import *
class Graph (Structure):
    _fields_ = [("numVertices", c_ulong),
                    ("numEdges", c_ulong)]
    def __init__(self):
        self.numVertices = 0
        self.numEdges = 0

    def __deepcopy__(self,memo={}):
        newInstance = Graph()
        newInstance.numVertices = self.numVertices
        newInstance.numEdges = self.numEdges
        return newInstance

graph = Graph()
anotherGraph = copy.deepcopy(graph)

您可以通过从类派生来抑制转换,但这通常是不必要的。一个用例是使用 ctypes 调用返回分配字符串的函数。您需要禁止 c_char_p 到 Python 字节字符串的转换,以便稍后释放 c_char_p。

from ctypes import *

class ulong(c_ulong): pass
class char_p(c_char_p): pass

class Test(Structure):
    _fields_ = [('a',ulong),
                ('b',char_p)]

t = Test(1,b'hello')
print(type(t.a),type(t.b))
print(t.a,t.b)

输出:

<class '__main__.ulong'> <class '__main__.char_p'>
<ulong object at 0x0000000006263748> char_p(b'hello')

【讨论】:

    猜你喜欢
    • 2015-07-31
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多