ctypes 将 c_uint64 转换为 c_char_p
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
失败?
如果 sizeof
两种类型相同,是否有任何替代 ctypes.cast
的方法?
from ctypes import *
and
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
Why does the cast
fail?
Is there any alternative to ctypes.cast
which always works if sizeof
both types is the same?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
c_uint64 是内存地址吗?如果是这样,那么您可以这样做:(
请参阅 http://docs.python。 org/library/ctypes.html#ctypes.c_char_p)
或者,如果您想要做的是将 c_uint64 中存储的值重新解释为 8 字节以 null 结尾的字符缓冲区,那么您需要将指向 c_uint64 的指针转换为 c_char_p...
看起来 ctypes 会保护您免受缓冲区溢出(如果它不是空终止的话):
更新以响应 Albert 的评论:
原因的答案在文档和代码中 - http://docs.python.org/library/ctypes.html#ctypes.cast
合约在 代码如下:
因此,强制转换的第一个参数(对象)必须可转换为 c_void_p。在源中,检查输出 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 中的情况可能并非如此。
至于理由 - 这个问题必须向开发人员提出。
据我所知,解决方案正如我在第一个示例中所示的那样。使用 Python 整数构造指针或将其分配给指针对象的值成员(转换器知道如何从 Python 整数进行转换)。 cast() 不会起作用,因为它就是这样实现的。
Is the c_uint64 a memory address? If so, then you can do this:
(see http://docs.python.org/library/ctypes.html#ctypes.c_char_p)
Or, if what you want to do is reinterpret the value stored in the c_uint64 as an 8 byte null-terminated character buffer then you need to cast a pointer to the c_uint64 as the c_char_p...
It looks like ctypes will protect you from buffer overruns if it's not null-terminated:
UPDATE in response to Albert's comment:
The answer to why is in the documentation and the code - http://docs.python.org/library/ctypes.html#ctypes.cast
The contract is enforced in the code as such:
So the first argument to cast (the object) must be convertible to a c_void_p. In the source, check out c_void_p_from_param(). This is where conversion to c_void_p is done. There are converters for Python integers, Python strings, Python unicode strings, c_void_p, ctypes array/pointer, byref results, function pointers, c_char_p/c_wchar_p, and any object that has the _as_parameter_() method defined.
There are no converters for ctypes integer objects. I am only looking at 2.6 code (as that's what you're using), so that might not be the case in 2.7 or 3.x.
As for the rationale - that question would have to be presented to the developers.
As far as I know, the solution is just as I showed with the first example. Construct pointers with or assign to the value member of pointer objects with Python integers (the converter knows how to convert from Python integers). cast() will not work because that's how it was implemented.
您必须获取指向该值的指针,请检查以下内容:
You have to obtain a pointer to the value, check this:
我现在要这样:
看起来有点复杂,但我还没有真正找到更简单的方法。
I'm going this way now:
Looks somewhat complicated but I haven't really figured out a simpler way.