python ctypes总结

核心概念

ctypes官方

  • 类型一览

ctypes是python定义的为实现类型转换的中间层,是纯python数据类型与c类型通信的桥梁.
Screenshot from 2019-01-03 11-33-04-fecf6500-f845-4dd4-bc06-2deb65be7f33

除了None,integer,string,bytes,(隐式转换), 其他都需要转换成ctypes类型作为参数.

None -->NULL
string bytes -- > char* wchar_t*
integer -- > int
#c_double 必须显示转换
printf(b'Hello %s %f\n', b'Wisdom', c_double(1.23))

标准类型里唯一要注意的是c_char_p,很像C里的字符串类型, 它只能转换integer或者bytes作为输入.

普通的’char *'类型用POINTER(c_char)

class ctypes.c_char_p
Represents the C char * datatype when it points to a zero-terminated string. For a general character pointer that may also point to binary data, POINTER(c_char) must be used. The constructor accepts an integer address, or a bytes object.
  • 严格区分类型

不像c指针那么万能,python里一切皆对象.数组,指针都是要按不同的类型来分开的。

1 int a = 100;  
    ----> ct_a = c_int(100)
2 int array[100] = {0,1,2,...} 
    ---->ct_array = (c_int* 100)(0,1,2,...)
         for i in ct_array: print(i)
3 int *ptr = &a;  
    ----> ct_ptr = POINTER(c_int)(ct_a)
          ct_ptr.contents
          c_int(10)
4 *ptr = 200 ;
// ptr[0] = 200
    ----> ct_ptr[0] = 200 or ct_ptr.contents.value = 300
5 int *ptr_arr = array;
    ---->  ctype做不到! 对python 来讲,数组和指针是不同的类型 
  • Access dll function and values

function见下面例2.

value:

>>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag")
>>> print(opt_flag)
c_long(0)
  • resttype argstype

load c的lib后,必须告诉Python,一个ctype函数的形参类型和返回的值的类型, 函数才能正确地在python里调用.

libusb_alloc_transfer = libusb.libusb_alloc_transfer
libusb_alloc_transfer.argtypes = [c_int]
libusb_alloc_transfer.restype = libusb_transfer_p
  • convert python type to ctype

1.构造ctype对象时输入;

2.通过value输入输入;

ct_int = ctypes.c_int(100)
ct_int.value
100
ct_int.value = 200
ct_int
c_int(200)

如果是ctype指针,也是要通过赋值:
但是python的bytes是immutable的,也就是bytes内容变化,是指向了另外的内存,而不是内存内容本身发生了变化,这和c的一些要求是不符合的:

ct_str = ctypes.c_wchar_p('Hi!')
ct_str.value
'Hi!'
ct_str
c_wchar_p(140093580736096)
ct_str = ctypes.c_wchar_p('Hi again')
ct_str.value
'Hi again'
ct_str
c_wchar_p(140093530479112)

用下面的 create_string_buffer解决问题

  • create_string_buffer
    创建可修改的ctype内存空间
>>buf = create_string_buffer(b'12345')
>>buf.value
>>b'12345'
  • byref and pointer and POINTER

byref:

拿到ctype instance的指针对象,,offset是偏移的地址. 但是只能用作ctype函数的参数,比pointer(obj)更快.

pointer:

pointer则是构造ctype对象的ctype pointer实例对象,普通对象变成指针对象

ctypes.pointer(obj)
Pointer instances are created by calling the pointer() function on a ctypes type.
This function creates a new pointer instance, pointing to obj. The returned object is of the
type POINTER(type(obj)).

用contents取出内容,类似于*a:

  • POINTER

POINTER仅仅是ctype层面的指针类型转换,比如1个ctypes类型转成其指针的类型,类型变成指针类型

ctypes.POINTER(type)
This factory function creates and returns a new ctypes pointer type. Pointer types are
cached and reused internally, so calling this function repeatedly is cheap. type must be a
ctypes type.

例子:

libc.printf(b'%x',byref(c_int(123)))
>>bf60f9188
type(byref(c_int(123)))

ct_int = ct_int(123)
>> <class 'CArgObject'>
ip = pointer(ct_int)
type(ip)
>> <class '__main__.LP_c_int'>
ip.contents
>>c_int(0)
type_int_p = POINTER(c_int)
type(type_int_p)
>> <class '_ctypes.PyCPointerType'>
ip_1 = type_int_p(c_int(123))
ip_1.contents
>>c_int(123)
type(ip_1)
<class '__main__.LP_c_int'>
>>False
  • Structure

参考下面例子里定义.

1.注意一点,字节序是native bytes order.

2.前向声明结构体的方式:

>>> from ctypes import *
#先声明1个空的
>>> class cell(Structure):
...     pass
...
#直接赋值_fields_的属性
>>> cell._fields_ = [("name", c_char_p),
...                  ("next", POINTER(cell))]
>>>
  • Array

不同类型再乘以1个数即得到数组.

ct_int_array = c_int * 10
type(ct_int_array)
<class '_ctypes.PyCArrayType'>
  • memmove memset
ctypes.memmove(dst, src, count)
Same as the standard C memmove library function: copies count bytes from src to dst. dst and src must be integers or ctypes instances that can be converted to pointers.

ctypes.memset(dst, c, count)
Same as the standard C memset library function: fills the memory block at address dst with count bytes of value c. dst must be an integer specifying an address, or a ctypes instanc
  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值