【高级教程】ctypes:从python菜鸟到c大神2

这篇博客详细介绍了ctypes库的实用函数和数据类型,包括addressof、create_string_buffer、DllCanUnloadNow、find_library等,以及基础数据类型、结构化数据类型、array和pointer的使用。通过实例展示了如何利用ctypes进行C语言级别的操作,适合Python开发者深入理解ctypes。

上一篇主要从理论指导上介绍ctypes,这一篇将从操作指南方面介绍ctypes。相当多的语句特性、细节都体现在例子中,请仔细分析。诸位的批评教育就是我进步上升空间,欢迎指教。

目录

1、ctypes实用函数

1.1 addressof、alignment、byref、cast

1.2 create_string_buffer、create_unicode_buffer

1.3 DllCanUnloadNow、DllGetClassObject

1.4 find_library、find_msvcrt

1.5 FormatError、GetLastError、get_errno、get_last_error

1.6 set_errno、set_last_error

1.7 memmove、memset、POINTER、pointer、resize

1.8 sizeof、string_at、wstring_at、WinError

2、数据类型

2.1 _CData

2.1.1 公共方法

2.1.2 公共属性

2.2 基础数据类型

2.2.1 _SimpleCData

2.2.2 基础数据类型

2.3 结构化数据类型

2.3.1 _fields_

2.3.2 _pack_

2.3.4 _anonymous_

2.4 array和pointer


1、ctypes实用函数

>>> from ctypes import *
>>>

1.1 addressof、alignment、byref、cast

addressof(obj):返回ctypes类型实例obj的内存块地址(整数)。

alignment(obj_or_type):返回ctypes类型或实例obj_or_type所要求的对齐。

byref(obj[,offset]):返回一个指向ctypes类型实例obj的轻量级指针。offset是一个整数,默认为0,表示相对于内部指针(首地址)的偏移。

byref(obj,offset)对应c代码如下:

(((char*)&obj)+offset)

byref()函数返回值只能用于外部函数参数。其行为类似于pointer(obj),但要快得多。

cast(obj,type):函数作用类似于c类型转换运算,返回一个指向obj内存块的type类型pointer实例。type必须是一个pointer类型,并且obj必须能解析为pointer对象。

>>> a=c_int(90)
>>> addr=addressof(a)
>>> s=c_char_p(addr)
>>> s.value
b'Z'
>>> a.value=65
>>> s.value
b'A'
>>> alignment(a)
4
>>> alignment(c_double)
8
>>> class POINT(Structure):
      _fields_=[('x',c_int),('y',c_int)]
>>> p1=POINT(540,960)        
>>> print(POINT.y)     
<Field type=c_long, ofs=4, size=4>
>>> def sayHi(Cint):
           print('Hi',cast(Cint,POINTER(c_int)).contents.value)
>>> sayHi(byref(p1,4))
Hi 960
>>>

1.2 create_string_buffer、create_unicode_buffer

create_string_buffer(init_or_size,size=None)

创建一个可写内存块,返回c_char数组。init_or_size必须是一个整数以指明数组大小,或者是一个初始化数组各项的字节串对象

如果init_or_size是字节串对象,数组将在长度上大于字节串对象,以使最后一个元素为NUL终止符。如果字节串对象仅用于初始化数组元素,则可用第二个参数size指定数组长度。源码:

def create_string_buffer(init, size=None):

    if isinstance(init, bytes):

        if size is None:

            size = len(init)+1

        buftype = c_char * size

        buf = buftype()

        buf.value = init

        return buf

    elif isinstance(init, int):

        buftype = c_char * init

        buf = buftype()

        return buf

    raise TypeError(init)

create_unicode_buffer(init_or_size,size=None)

创建一个可写内存块,返回c_wchar数组。init_or_size必须是一个整数以指明数组大小,或者是一个初始化数组各项的字符串(str)对象

如果init_or_size是字符串对象,数组将在长度上大于字符串对象,以使最后一个元素为NUL终止符。如果字符串对象仅用于初始化数组元素,则可用第二个参数size指定数组长度。源码:

def create_unicode_buffer(init, size=None):

    if isinstance(init, str):

        if size is None:

            size = len(init)+1

        buftype = c_wchar * size

        buf = buftype()

        buf.value = init

        return buf

    elif isinstance(init, int):

        buftype = c_wchar * init

        buf = buftype()

        return buf

    raise TypeError(init)

create_string_buffercreate_unicode_buffer最大不同之处在于返回的数组类型(一个字符元素几个字节)。当一个函数希望能够修改某个参数所指内存块内容时,不能传递c_char_p、c_wchar_p、c_void_p实例,而应传递create_string_buffer/create_unicode_buffer创建的实例或其他POINTER/pointer/array实例。

>>> a=b'abcde'      
>>> pi=c_char_p(a)     
>>> pi.value
b'abcde'
>>> pi.value=b'cdef'
>>> a
b'abcde'
>>> pi=create_string_buffer(a)
>>> pi.value
b'abcde'
>>> pi.raw
b'abcde\x00'
>>> pi.value=b'123'
>>> pi.value
b'123'
>>> pi.raw     
b'123\x00e\x00'
>>> a       
b'abcde'
>>> a=create_unicode_buffer('abcde')            
>>> a.value           
'abcde'
>>> a.raw
AttributeError: 'c_wchar_Array_6' object has no attribute 'raw'
>>> sizeof(a)         
12
>>>

valueraw的区别:前者所见即NUL串,后者所见即所得(数组内容)。

1.3 DllCanUnloadNow、DllGetClassObject

这两个函数是仅限windows的钩子函数,支持通过ctypes实现in-process COM服务器(DLL运行在包含自身的应用程序进程空间)。内部将调用comtypes.server.inprocserver导出的同名函数。

1.4 find_library、find_msvcrt

ctypes.util.find_library(name):查找函数库并返回其路径名。name是不带任后前缀(如lib)、后缀(如.so,.dylib)或版本号(由posix链接选项-l生成)的库名,查找失败时返回None。本函数实际功能依赖于系统。

ctypes.util.find_msvcrt():仅限windows,返回python及扩展模块使用的VC运行时库文件名。如果函数库名未定义,则返回None。

如果要释放某个扩展模块分配的内存,则使用与内存分配函数同库的内存释放函数(例如free(void*))相当重要。

1.5 FormatError、GetLastError、get_errno、get_last_error

ctypes.FormatError([code]):仅限windows,返回错误代码code的文本描述。如果未指定code,则使用windows API函数GetLastError()获取的错误代码。

ctypes.GetLastError():仅限windows,返回所在线程windows设置的最近错误代码。此函数直接调用windo

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值