from ctypes import *
和
In [27]: sizeof(c_char_p)
Out[27]: 8
In [28]: sizeof(c_uint64)
Out[28]: 8
In [29]: cast(c_uint64(0), c_char_p)
---------------------------------------------------------------------------
ArgumentError Traceback (most recent call last)
/Users/az/Programmierung/PyCPython/<ipython console> in <module>()
/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ctypes/__init__.pyc in cast(obj, typ)
479 _cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
480 def cast(obj, typ):
--> 481 return _cast(obj, obj, typ)
482
483 _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
ArgumentError: argument 1: <type 'exceptions.TypeError'>: wrong type
为什么cast
会失败?
如果ctypes.cast
这两种类型相同,那么sizeof
是否总有效?
答案 0 :(得分:3)
c_uint64是内存地址吗?如果是这样,那么你可以这样做:
>>> n = c_uint64(1234567890) #assume this is a valid memory address...beware of segfaults
>>> p = c_char_p(n.value)
>>> #or..
>>> p.value = n.value #special semantics for c_char_p - accepts both addresses and strings
(见http://docs.python.org/library/ctypes.html#ctypes.c_char_p)
或者,如果您要做的是将存储在c_uint64中的值重新解释为8字节以空字符结尾的字符缓冲区,那么您需要将指向c_uint64的指针转换为c_char_p ...
>>> n = c_uint64(ord("A"))
>>> n
c_ulong(65L)
>>> p = cast(pointer(n), c_char_p)
>>> p
c_char_p(47101614291216)
>>> p.value
'A'
如果它不是以空值终止的话,看起来ctypes会保护你免受缓冲区溢出:
>>> n2 = c_uint64(0xFFFFFFFFFFFFFFFF)
>>> p2 = cast(pointer(n2), c_char_p)
>>> p2.value[0]
'\xff'
>>> p2.value
'\xff\xff\xff\xff\xff\xff\xff\xff'
>>> p2.value[9]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
更新以回应Albert的评论:
我想知道为什么演员阵容在这里不起作用
原因在于文档和代码 - http://docs.python.org/library/ctypes.html#ctypes.cast
ctypes.cast(obj,type) 此函数类似于C中的强制转换运算符。它返回一个新的类型实例,它指向与obj相同的内存块。 type必须是指针类型,和obj必须是可以的对象 被解释为指针。
合同在code中强制执行:
_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
def cast(obj, typ):
return _cast(obj, obj, typ)
因此,施放的第一个参数(对象)必须可转换为c_void_p。在source中,查看c_void_p_from_param()。这是转换为c_void_p的地方。有Python整数转换器,Python字符串,Python unicode字符串,c_void_p,ctypes数组/指针,byref结果,函数指针,c_char_p / c_wchar_p,以及定义了_as_parameter_()方法的任何对象。
ctypes整数对象没有转换器。我只关注2.6代码(就像你正在使用的那样),所以在2.7或3.x中可能不是这种情况。
至于理由 - 这个问题必须提交给开发者。
...如果有通用版本总是有效(对于所有情况,不是 只是c_char_p)。
据我所知,解决方案正如我在第一个例子中所展示的那样。使用Python整数构造指针或指定给指针对象的value成员的指针(转换器知道如何从Python整数转换)。 cast()将不起作用,因为它是如何实现的。
答案 1 :(得分:0)
您必须获取指向该值的指针,请检查:
In [29]: i = c_uint32(0x30313233)
In [30]: cast(pointer(i), c_char_p).value
Out[30]: '3210'
答案 2 :(得分:0)
我现在正走这条路:
def isPointerType(t):
if issubclass(t, _ctypes._Pointer): return True
return False
def getValueOf(obj):
if isPointerType(obj.__class__):
return cast(obj, c_void_p).value
else:
return obj.value
def static_cast(obj, t):
newObj = t()
if isPointerType(t):
cast(pointer(obj), POINTER(c_void_p)).contents.value = getValueOf(obj)
else:
newObj.value = getValueOf(obj)
return newObj
看起来有些复杂,但我还没有想出更简单的方法。