byref 并不会构造一个指针对象,因此速度比 pointer 快,只能作为导出函数的实参使用。其 _obj 是只读属性,不能更改。
pointer 会构造一个指针对象。.contents 属性即其所指的对象,但是指向是能够变动的。相当于
int *ptr = n;
ptr = &m; //指向可以变化
对于一个包含如下函数,名为 lib.so 动态库:
void change(float* ptr, float value)
{
*ptr = value;
}
ptr.contents 更改指针的指向,change 函数调用后,c的值并没有变化,变化的是 ptr.contents 的值。
ctypes.addressof 返回 C 实例的地址,可以查看区别:
ctypes.addressof(ptr.contents)
ctypes.addressof(c)
POINTER 返回类型对象,用来给 restype 和 argtypes 指定函数的参数和返回值的类型用。
ctypes.POINTER(ctypes.c_float) == type(ptr) #True ptr的类型可通过 POINTER 获得
如果不指定,默认的类型都将被当做是整形。实参类型(除了 None,integer,stringbytes,可隐式转换)和返回值的类型用 ctypes.c_ 系列类型显示的指定。(见ctypes 文档:None
, integers, bytes objects and (unicode) strings are the only native Python objects that can directly be used as parameters in these function calls.)
实际上,最终得到的返回结果的类型已经由显示指定的ctypes.c_ 类型,转化为了对应的 python 类型。比如指定 .restype = c_char_p,函数的返回值的类型将是 bytes 类型。
根据 ctypes 官方文档的描述:ctypes实例由一个内存块和若干描述符构成,描述符用来访问内存块。内存块并不保存 python 对象,而仅仅保存 python 对象的内容。外部访问保存的内容时,都会构造一个新的 python 对象。
所以
c_instanc.value is c_instanc.value #False
c_instance.content is c_instance.content #False