ctypes 类型转换

隐式转换

首先我们在c语言里面,两边都可以向中间转换

非数字类型 整型 浮点型
char   float
unsigned char int double
*   long

那么在python中。

如果你的参数中有一个指针类型的 POINTER(),或者是有一个结构体成员中有这一类型。只有实例对象和类型完全一样才会接受。(显示声明传入类型在前面有提到,通过属性argtypes进行限定)

特例:如果你传入一个兼容的array对象而不是pointer对象。那么对于POINTER(c_int),ctypes会接受一个c_int的数组。同c语言的指针和数组关系。

>>> class Bar(Structure):
...     _fields_ = [("count", c_int), ("values", POINTER(c_int))]
...
>>> bar = Bar()
>>> bar.values = (c_int * 3)(1, 2, 3)
>>> bar.count = 3
>>> for i in range(bar.count):
...     print(bar.values[i])
...
1
2
3
>>>

如果一个方法显示的声明了是一个指针类型,比如()POINTER(c_int),那么如果是一个被指向类型的参数,

这种情况下。ctypes将会通过byref自动做出调整。

如果需要的是 POINTER(c_int)传入int,就会自动的通过  byref(c_int)进行生成一个指针类型。

如果创建一个空指针,设置一个空指针

bar.values = None

强制转换  cast

有时候类型不匹配,在c中,可以通过强制转换。

ctypes中提供了  cast 方法来实现。

接着上面的Bar类,我们可以知道Bar结构体定义了接受指针或者是数组的values字段,而不是其他类型。

>>> bar.values = (c_byte * 4)()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
>>>

在上面的案例,传入了一个长度为4的c_byte数组,并且初始值为0.但是接受的是 一个c_int。

对于这种情况下,cast方法是非常方便的。

cast方法可以用来将C风格的普通类型转化成为指向其他类型的C类型。

cast接受两个参数z,c风格的类型是一个指针或者是可以被转换为一个指针。返回第二个参数类型的对象。

cast也就是某一种指针转换成为另一种指针,然后指向的内存一样,也就是地址不变。

>>> bar = Bar()
>>> bar.values = cast((c_byte * 4)(), POINTER(c_int))
>>> print(bar.values[0])
0
>>>

这里,我们可以看到这是一个大端序

我们看一下linux的

也就是默认是大端序

通过C测试出来 也是大端。

大端方便我们阅读,偏移的时候也可以从低位往高位偏移。如果溢出,那么就使用未溢出也就是合法内存内的数据。

这种即使在溢出的情况下,低位的仍然保持数据的正确性。而且,网络字节序也是大端。

大端大端,即大在端点,小在起点。

>>> bar = Bar()
>>> bar.values = cast((c_byte * 4)(), POINTER(c_int))
>>> print(bar.values[0])
0
>>>

同样的cast的结果可以用来给values赋值。

猜你喜欢

转载自blog.csdn.net/rubikchen/article/details/89525604