2022年python-ctypes模块中文帮助文档 .pdf

上传人:C****o 文档编号:40153000 上传时间:2022-09-08 格式:PDF 页数:23 大小:157.32KB
返回 下载 相关 举报
2022年python-ctypes模块中文帮助文档 .pdf_第1页
第1页 / 共23页
2022年python-ctypes模块中文帮助文档 .pdf_第2页
第2页 / 共23页
点击查看更多>>
资源描述

《2022年python-ctypes模块中文帮助文档 .pdf》由会员分享,可在线阅读,更多相关《2022年python-ctypes模块中文帮助文档 .pdf(23页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、内容:.加载动态链接库.从已加载的dll 中引用函数.调用函数 1.基本的数据类型.调用函数 2.用自己的数据类型调用函数.确认需要的参数类型(函数原型).返回值.传递指针.结构和联合.结构或联合的对齐方式和字节的顺序.结构和联合中的位.数组.指针.类型转换.未完成的类型.回调函数.访问 dlls 导出的值.可变长度的数据类型.bugs 将要做的和没有做的事情注意:本文中的代码例子使用doctest 确保他们能够实际工作。一些代码例子在linux 和windows 以及苹果机上执行有一定的差别注意:一些代码引用了ctypes 的 c_int 类型。它是c_long 在 32 位机子上的别名,你

2、不应该变得迷惑,如果你期望的是 c_int 类型,实事上打印的是c_long,它们实事上是相同的类型。加载动态链接库ctypes 加载动态链接库,导出cdll 和在 windows 上同样也导出windll 和 oledll 对象。加载动态链接库后,你可以像使用对象的属性一样使用它们。cdll 加载使用标准的cdecl 调用约定的链接库,而 windll 库使用stdcall 调用约定,oledll 也使用stdcall 调用约定,同时确保函数返回一个windows HRESULT错误代码。这错误代码自动的升为WindowsError Python exceptions,当这些函数调用失败时。

3、这有一些windows 例子,msvcrt 是微软的c 标准库,包含大部分的标准c 函数,同时使用cdecl 调用约定。注:cdecl 和 stdcall 的区别请见http:/ from ctypes import*print windll.kernel32#doctest:+WINDOWS 名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 23 页 -print cdll.msvcrt#doctest:+WINDOWS libc=cdll.msvcrt#doctest:+WINDOWS windows 自动添加常用的.dll 文件后缀名在 linux 上,需要使用包含扩展名的文

4、件名来加载一个库,因此属性操作不能正常使用。或者使用 dll 加载器的LoadLibrary 方法,或者通过CDLL构造函数创建一个CDLL的一个实例 cdll.LoadLibrary(libc.so.6)#doctest:+LINUX libc=CDLL(libc.so.6)#doctest:+LINUX libc#doctest:+LINUX 加载 dll 使用其中函数使用函数就像对象的属性 from ctypes import*libc.printf print windll.kernel32.GetModuleHandleA#doctest:+WINDOWS print windll.

5、kernel32.MyOwnFunction#doctest:+WINDOWS Traceback(most recent call last):File,line 1,in?File ctypes.py,line 239,in _getattr_ func=_StdcallFuncPtr(name,self)AttributeError:function MyOwnFunction not found 00 注意win32 系统 dll 像 kernel32 和 user32 大部分导出ANSI和 UNICODE版本函数,UNICODE版本以一个W 结尾导出而 ANSI版本则以一个A 结尾导

6、出的。win32 GetModuleHandle 函数,返回一个指定的module名字的 module 句柄下面 c 原型,GetModuleHandle 的 macro,依赖于它是不是UNICODE。/*ANSI version*/HMODULE GetModuleHandleA(LPCSTR lpModuleName);/*UNICODE version*/HMODULE GetModuleHandleW(LPCWSTR lpModuleName);名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 23 页 -windll不 会 神 奇 的 自 已 去 选 择 一 个,你 必

7、须 显 式 确 认GetModuleHandleA或 者GetModuleHandleW 去使用它们去处理一般字符串或unicode 字符串。有时候,dll 导出函数名,python 无法识别,像?2YAPAXIZ.在这情况下,你必须使用getattr 去使用这些函数 getattr(cdll.msvcrt,?2YAPAXIZ)#doctest:+WINDOWS 在 windows 上,一些dllS 不是导出函数名,而是以顺序,这些函数可以将这些数字当作dll对象的索引来使用这些函数。cdll.kernel321#doctest:+WINDOWS cdll.kernel320#doctest:

8、+WINDOWS Traceback(most recent call last):File,line 1,in?File ctypes.py,line 310,in _getitem_ func=_StdcallFuncPtr(name,self)AttributeError:function ordinal 0 not found 调用函数你可调用这些函数,像其它的python 函数一样,下面的例子使用time()函数,它以秒为单位返回从unix 新纪元的系统时间,GetModuleHandleA()函数,返回一个win32 模块句柄。下面的例子用空指针调用函数(None 作为空指针)pr

9、int libc.time(None)#doctest:+SKIP 1150640792 print hex(windll.kernel32.GetModuleHandleA(None)#doctest:+WINDOWS 0 x1d000000 ctypes 尝试阻止你以错误的参数数量或调用约定来调用函数。不幸的是,这些仅仅能在windows 上工作它在函数返回后不会去检查这栈,尽管在调用函数后有错误发生。windll.kernel32.GetModuleHandleA()#doctest:+WINDOWS Traceback(most recent call last):名师资料总结-精品资

10、料欢迎下载-名师精心整理-第 3 页,共 23 页 -File,line 1,in?ValueError:Procedure probably called with not enough arguments(4 bytes missing)windll.kernel32.GetModuleHandleA(0,0)#doctest:+WINDOWS Traceback(most recent call last):File,line 1,in?ValueError:Procedure probably called with too many arguments(4 bytes in exce

11、ss)产生了同样的exception,当你用cdecl 调用约定去使用一个stdcall 函数,反之亦然。cdll.kernel32.GetModuleHandleA(None)#doctest:+WINDOWS Traceback(most recent call last):File,line 1,in?ValueError:Procedure probably called with not enough arguments(4 bytes missing)windll.msvcrt.printf(spam)#doctest:+WINDOWS Traceback(most recent

12、call last):File,line 1,in?ValueError:Procedure probably called with too many arguments(4 bytes in excess)找到正确的调用约定,你必须检查c 头文件或者你想调用的函数的文档。在 windows,ctypes 使用 win32 结构 exception 处理一般的保护错误阻止crashes,当调用无效的参数值 windll.kernel32.GetModuleHandleA(32)#doctest:+WINDOWS Traceback(most recent call last):File,li

13、ne 1,in?WindowsError:exception:access violation reading 0 x00000020 然而有很多种可能性会发生crash,你使用 python 的 ctypes,你应该足够的小心。None,integers,longs,byte strings 和 unicode string 是 python 内置对象,可以直接的作为这些函数的参数,None 作为一个空指针,byte string 和 unicode string 当作一个内存块,它包含这些数据(char*或者wchar_t*)。python 的 int 和 long 长整形作为c int

14、类型,它们的值对应着c 类型。在调用带有参数的函数之前,我们必须学习更多的关于ctypes 数据类型。名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 23 页 -基础的数据类型ctypes 定义了许多主要的c 兼容有数据类型数据类型请见http:/ c_int()c_long(0)c_char_p(Hello,World)c_char_p(Hello,World)c_ushort(-3)c_ushort(65533)因此这些类型是可变的,他们的值在后面也是可以改变的分配一个新值到这些指针类型c_char_p,c_wchar_p,和 c_void_p 的一个实例上,改变它们指向的内

15、存位置,而不是这些内存块的内容(当然,因为python 的 string 是不可改变的)s=Hello,World c_s=c_char_p(s)print c_s c_char_p(Hello,World)c_s.value=Hi,there print c_s c_char_p(Hi,there)print s#first string is unchanged Hello,World 你应该注意,不要期望传给函数指针是指向可变的内存。如果你需要可变的内存块,ctypes有一个create_string_buffer 函数。这内存块内容通过这raw 属性来访问或改变,如果你想访问一个以 n

16、ull 结束的字符串,使用这string 属性 from ctypes import*p=create_string_buffer(3)#create a 3 byte buffer,initialized to NUL bytes print sizeof(p),repr(p.raw)名师资料总结-精品资料欢迎下载-名师精心整理-第 5 页,共 23 页 -3 x00 x00 x00 p=create_string_buffer(Hello)#create a buffer containing a NUL terminated string print sizeof(p),repr(p.r

17、aw)6 Hellox00 print repr(p.value)Hello p=create_string_buffer(Hello,10)#create a 10 byte buffer print sizeof(p),repr(p.raw)10 Hellox00 x00 x00 x00 x00 p.value=Hi print sizeof(p),repr(p.raw)10 Hix00lox00 x00 x00 x00 x00 create_string_buffer 代替 c_buffer(这个到目前是以别名存在的)函数,就像早期版本ctypes的 c_string 函数。create

18、_unicode_buffe 函数创建一个包含c类型 wchar_t 的 unicode 字符的可变的内存块调用函数 2 注意这printf打印到实际的标准的输出管道,而不是sys.stdout,所以这些例子仅仅工作在console 下,而不能在idle 或 pythonwin 下工作。printf=libc.printf printf(Hello,%sn,World!)Hello,World!14 printf(Hello,%S,uWorld!)Hello,World!13 printf(%d bottles of beern,42)42 bottles of beer 19 printf(

19、%f bottles of beern,42.5)Traceback(most recent call last):File,line 1,in?ArgumentError:argument 2:exceptions.TypeError:Dont know how to convert parameter 2 就像以前提到的,所有的python 类型除了integer,string,unicode string 以外必须以一个合适的 ctypes 类型包装,名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 23 页 -这样它们才能转换成需要的c 数据类型。printf(An int

20、%d,a double%fn,1234,c_double(3.14)Integer 1234,double 3.1400001049 31 使用你自定义的数据类型调用函数你可以自定义ctypes 参数,来让你自己的classes 的实例作为函数的参数。ctypes 寻找_as_parameter_ 属性作为函数的参数。当然,它必须是整形,字符串,或unicode class Bottles(object):.def _init_(self,number):.self._as_parameter_=number.bottles=Bottles(42)printf(%d bottles of be

21、ern,bottles)42 bottles of beer 19 如果你不想保存实例的数据在_as_parameter_ 实例的变量中,你应该定义一个属性使这个数据有效。定义需要的参数类型(函数原型)可以通过设置argtypes 属性,定义从dll 中导出的需要的参数类型。argtypes 必须是c 数据类型的一个列表(这里的printf 可能不是很好的例子,因为它是一个取决于format 字符串的可变数目的,需要不同类型的参数,使用这种特性是一种不错的特性)printf.argtypes=c_char_p,c_char_p,c_int,c_double printf(String%s,In

22、t%d,Double%fn,Hi,10,2.2)String Hi,Int 10,Double 2.200000 37 定义一个format 阻止了不兼容的参数类型(仅仅是一个c 函数的原型),尝试转换这些参数到合适的类型。printf(%d%d%d,1,2,3)Traceback(most recent call last):File,line 1,in?名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 23 页 -ArgumentError:argument 2:exceptions.TypeError:wrong type printf(%s%d%f,X,2,3)X 2 3.

23、00000012 12 如果你定义了你自己的类去传给调用函数,你必须使用from_param 类方法,这样就可以在argtypes 列表中使用它们。from_param 类方法接收传给函数的Python 对象,它做一个类型检测,或者确保这个对象是可接受的就返回这个对象本身,它的 _as_parameter_属性,或者你想作为参数传递给c函数的任何东西。这结果必须是一个整数,字符串,unicode,一个ctypes 的实例,或者任何有_as_parameter_属性的对象。返回值主要的函数都返回c int 类型,其它的返回类型可以通过设置function 对象的 restype 属性这有一个更好

24、的例子,它使用strchr 函数,它期望一个string 指针和一个char,同时返回一个指向 string 的指针。strchr=libc.strchr strchr(abcdef,ord(d)#doctest:+SKIP 8059983 strchr.restype=c_char_p#c_char_p is a pointer to a string strchr(abcdef,ord(d)def print strchr(abcdef,ord(x)None 如果你想避免上面的ord(x)调用,你可以设置 argtypes 属性,这第二个参数会从一个python字符到一个c char 字符

25、 strchr.restype=c_char_p strchr.argtypes=c_char_p,c_char strchr(abcdef,d)def strchr(abcdef,def)Traceback(most recent call last):File,line 1,in?ArgumentError:argument 2:exceptions.TypeError:one character string expected print strchr(abcdef,x)None strchr(abcdef,d)def 名师资料总结-精品资料欢迎下载-名师精心整理-第 8 页,共 23

26、页 -你可以使用一个可以调用的python 对象(一个函数或者一个class)作为这restype 属性的值,如果外部函数返回的是一个整数,这个可调用对象将调用这c 函数返回的整数,这个可调用对象的结果将作为这个函数调用的结果,这个对于检查返回值,同时产生一个错误很有帮助。GetModuleHandle=windll.kernel32.GetModuleHandleA#doctest:+WINDOWS def ValidHandle(value):.if value=0:.raise WinError().return value.GetModuleHandle.restype=ValidHa

27、ndle#doctest:+WINDOWS GetModuleHandle(None)#doctest:+WINDOWS 486539264 GetModuleHandle(something silly)#doctest:+WINDOWS Traceback(most recent call last):File,line 1,in?File,line 3,in ValidHandle WindowsError:Errno 126 The specified module could not be found.WinError 是一个函数,它调用Windows 的 FormatMessage

28、()API函数去获取一个错误码的描述,同时返回一个exception。WinError 采取一个可选择的错误代码参数,如果没有,它调用GetLastError()。请注意大量的错误检测机制是可行的,通过errcheck 属性,更多的细节请参考手册。传递指针和传递引用有时候,一个c API 函数期望一个指向某个数据类型的指针作为参数,可能要写入一些数据到相应的位置,如果这数据太大而不能传值。这同样适用于通过引用传递参数。ctypes 导出这 byref 函数,它用作通过引用传递参数。使用指针可以达到相同的效果,尽管指针可以做更多的事情,因为它初始化了一个指针对象,它比使用byref 要快,但在p

29、ython 中你不需要指针对象 i=c_int()f=c_float()s=create_string_buffer(000*32)名师资料总结-精品资料欢迎下载-名师精心整理-第 9 页,共 23 页 -print i.value,f.value,repr(s.value)0 0.0 libc.sscanf(1 3.14 Hello,%d%f%s,.byref(i),byref(f),s)3 print i.value,f.value,repr(s.value)1 3.1400001049 Hello 结构和联合Structures 和 unions 必须继承Structure 和 Unio

30、n 基础类,它们都在 ctypes 模块中定义,每一个子类必须定义一个_fields_属性,_fields_是一个 2 维 tuples 的列表,包含这field 的 name 和 field 的 type 这 field类型必须是一个ctypes 类型,像c_int,或者任何其它的继承ctypes 的类型,structure,union,array,指针。这里有一个简单的POINT结构,包含两个整型x 和 y,同样它也显示了如何在构造函数中初始化一个结构。from ctypes import*class POINT(Structure):._fields_=(x,c_int),.(y,c_i

31、nt).point=POINT(10,20)print point.x,point.y 10 20 point=POINT(y=5)print point.x,point.y 0 5 POINT(1,2,3)Traceback(most recent call last):File,line 1,in?ValueError:too many initializers 你可以创建很多更复杂的结构。结构可以通过包含一个结构类型的field 来包含其它的结构。下面是一外RECT结构,包含两个POINT名为 upperleft 和 lowerright。r=RECT(POINT(1,2),POINT(

32、3,4)r=RECT(1,2),(3,4)名师资料总结-精品资料欢迎下载-名师精心整理-第 10 页,共 23 页 -Field 描述可以从类中找到,这在调试中是很有用的,它可以提供非常有用的信息。print POINT.x print POINT.y Structure/union对齐和 byte 顺序默认 Structure/union的 field 对齐和 c 编译器的方式相同。通过在子类中定义一个_pack_ class 属性可以覆盖这个行为。这必须设置一个正数和为fields 对齐设置一个最大值。这就是#pragma pack(n)在MSVC中的作用。ctypes 使用结构和联合原始

33、的byte 顺序。使用一个非原始的byte 顺序创建结构,你可以使用 BigEndianStructure,LittleEndianStructure,BigEndianUnion,LittleEndianUnion 中的一个作为基础类。这些类不包含 pointer 的 field。Structure/union的 byte field 它是可以创建包含byte field 的 structures 和 unions byte field 仅仅可以适合整型field,这 bit的 width 通过这 _fields_元组中第三项来指定。class Int(Structure):._fields

34、_=(first_16,c_int,16),.(second_16,c_int,16).print Int.first_16 print Int.second_16 Array Array 是对列,包含一个固定数目的相同类型的实例。被推荐的方法去创建array 类型是对过一个数据类型与一个正数相乘。TenPointsArrayType=POINT*10 下面是一个人造数据类型的例子,一个结构包含4 个 POINT和一些其它的东西。名师资料总结-精品资料欢迎下载-名师精心整理-第 11 页,共 23 页 -from ctypes import*class POINT(Structure):._f

35、ields_=(x,c_int),(y,c_int).class MyStruct(Structure):._fields_=(a,c_int),.(b,c_float),.(point_array,POINT*4)print len(MyStruct().point_array)4 使用一般的方法创建实例,通过调用class arr=TenPointsArrayType()for pt in arr:print pt.x,pt.y 这上面打印了一系列的0,0 行,因为这队列的内容都初始化为0。正确类型的初始化也可以指定。from ctypes import*TenIntegers=c_int

36、*10 ii=TenIntegers(1,2,3,4,5,6,7,8,9,10)print ii for i in ii:print i,.1 2 3 4 5 6 7 8 9 10 指针通过调用ctypes 类型的指针函数来创建指针实例 from ctypes import*i=c_int(42)pi=pointer(i)指针实例有一个contents 属性,返回这个指针指向的对象,上面的i 对象。pi.contents c_long(42)名师资料总结-精品资料欢迎下载-名师精心整理-第 12 页,共 23 页 -注意这 ctypes 不包含面向对象,它每次查看一个属性时就创建一个全新的等价

37、的对象。pi.contents is i False pi.contents is pi.contents False 分配另外一个c_int 的实例到pointer 的内容属性,将导致指针指向存储它本身的内存位置。i=c_int(99)pi.contents=i pi.contents c_long(99)指针的实例也可以用整数来索引 pi0 99 分配一个整数索引将改变它指向的指针 print i c_long(99)pi0=22 print i c_long(22)你可以使用不同于0 整型的索引的指针,但是你必须知道你正在做什么,就像在 c 里面,你可以访访问或武断改变内存位置,一般而言

38、,当你从一个c函数接收一个指针,同时你知道这个指针实例指向的是一个array而不是单个项。在这种场景下,这指针函数比简单的创建一个指针实例要困难多,它首先必须通过POINTER函数创建一个可以接收任何ctypes 类型的指针类型,返回一个新类型。PI=POINTER(c_int)PI PI(42)Traceback(most recent call last):名师资料总结-精品资料欢迎下载-名师精心整理-第 13 页,共 23 页 -File,line 1,in?TypeError:expected c_long instead of int PI(c_int(42)不带参数的调用这指针类型

39、创建一个NULL指针,NULL指针有一个False 布尔值。null_ptr=POINTER(c_int)()print bool(null_ptr)False ctypes 检查 NULL非引用指针(非引用非关联指针会crash Python).null_ptr0 Traceback(most recent call last):.ValueError:NULL pointer access null_ptr0=1234 Traceback(most recent call last):.ValueError:NULL pointer access 类型转换一般而言,ctypes 进行严格的

40、类型检查,如果在函数参数列表中有一个POINT(c_int)类型或者在作为结构定义中一个成员field,仅仅接收这相同类型的实例。有一些exception 应用在这些规则上当 ctypes 接收其它类型的对象。例如你传递一个兼容的array 实例,代替指针类型。这样对于 POINTER(c_int),ctypes 可以接收c_int 型 array 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

41、 range(bar.count):.print bar.valuesi.1 名师资料总结-精品资料欢迎下载-名师精心整理-第 14 页,共 23 页 -2 3 设置一个指针类型为空,你可以分配None:bar.values=None 有时候,你有一些不兼容类型的实例。在 C中,你可以强制转换一个类型到另一个类型。ctypes提供了一个有相同作用的转换函数。这Bar structure 定义了一个POINTER(c_int)指针,或者c_int 的 array 的 field,但是没有其它类型。bar.values=(c_byte*4)()Traceback(most recent call

42、last):File,line 1,in?TypeError:incompatible types,c_byte_Array_4 instance instead of LP_c_long instance 对于这些例子,cast 函数是很不错的。使用 cast 函数将一个ctypes 实例转换成一个不同的ctypes 数据类型的指针。cast 对象有两个参数,一个ctypes 对象是或者可以转换成某些类型的指针,或一个 ctypes 指针类型。它返回这第二个参数的实例,它引用第一个参数相同的内存块。a=(c_byte*4)()cast(a,POINTER(c_int)因此,cast 可以使用

43、来分配Bar 的值域 bar=Bar()bar.values=cast(c_byte*4)(),POINTER(c_int)print bar.values0 0 未完成的类型完成的类型包括成员还没有定义的structure 或 union,array.在 c,他们是在前面声明,而在后面定义的:struct cell;/*forward declaration*/名师资料总结-精品资料欢迎下载-名师精心整理-第 15 页,共 23 页 -struct char*name;struct cell*next;cell;直接转换为ctypes 像这样,但是它不能工作:class cell(Struc

44、ture):._fields_=(name,c_char_p),.(next,POINTER(cell).Traceback(most recent call last):File,line 1,in?File,line 2,in cell NameError:name cell is not defined 但是,新类cell 在它自己的类声明中是无效的。在ctypes,可以定义cell 类,同时在类声明中设置 _fields_属性 from ctypes import*class cell(Structure):.pass.cell._fields_=(name,c_char_p),.(n

45、ext,POINTER(cell)尝试一下,我们可以创建cell 的两个实例,让他们指向他们自己。c1=cell()c1.name=foo c2=cell()c2.name=bar c1.next=pointer(c2)c2.next=pointer(c1)p=c1 for i in range(8):.print p.name,.p=p.next0.foo bar foo bar foo bar foo bar 名师资料总结-精品资料欢迎下载-名师精心整理-第 16 页,共 23 页 -回调函数ctypes 可以从 python 可调用对象中创建一个c 可调用的函数指针。这些通常被称为回调函

46、数。首先,你需要为回调函数创建一个类,这类知道这调用约定,返回类型,以及这函数需要接收的参数个数。CFUNCTYPE 工厂函数使用正常的cdecl 调用约定创建回调函数的类型,同时在windows 上,WINFUNCTYPE工厂函数使用 stdcall 调用给定为回调函数创建类型。这两个工厂函数的结果类型作为第一个参数,这些期望的参数类型回调函数作为这剩下的参数。这而使用标准的c 库 qsort 函数,它使用一个回调函数来帮助排序items。qsort 将使用来排序一个整数array.IntArray5=c_int*5 ia=IntArray5(5,1,7,33,99)qsort=libc.q

47、sort qsort.restype=None 必须接收一个指向数据的指针来调用qsort 函数排序,同时一个比较函数的指针,也就是回调函数。这回调函数接收两个items 的指针,如果第一个小于第二个它返回一个负数,如果相等,返回0,其它的就返回一个正数。我们的回调函数接收整型指针,同时必须返回一个整数。首先我们创建这回调函数的类型。CMPFUNC=CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int)第一次使用这回调函数,我们简单的打印我们获得的参数,然后返回一个0.def py_cmp_func(a,b):.print py_cmp_func,a,b.r

48、eturn 0.创建 c 可调用的回调函数 cmp_func=CMPFUNC(py_cmp_func)现在准备的差不多了名师资料总结-精品资料欢迎下载-名师精心整理-第 17 页,共 23 页 -qsort(ia,len(ia),sizeof(c_int),cmp_func)#doctest:+WINDOWS py_cmp_func py_cmp_func py_cmp_func py_cmp_func py_cmp_func py_cmp_func py_cmp_func py_cmp_func py_cmp_func py_cmp_func 我们知道如何访问指针的内容,我们重新定义回调函数

49、:def py_cmp_func(a,b):.print py_cmp_func,a0,b0.return 0.cmp_func=CMPFUNC(py_cmp_func)这是我们在windows 上得到的结果:qsort(ia,len(ia),sizeof(c_int),cmp_func)#doctest:+WINDOWS py_cmp_func 7 1 py_cmp_func 33 1 py_cmp_func 99 1 py_cmp_func 5 1 py_cmp_func 7 5 py_cmp_func 33 5 py_cmp_func 99 5 py_cmp_func 7 99 py_c

50、mp_func 33 99 py_cmp_func 7 33 在 linux 上这 sort 函数看起来工作的更有效,它进行了更少的对比,这很有趣。qsort(ia,len(ia),sizeof(c_int),cmp_func)#doctest:+LINUX py_cmp_func 5 1 py_cmp_func 33 99 py_cmp_func 7 33 py_cmp_func 5 7 py_cmp_func 1 7 名师资料总结-精品资料欢迎下载-名师精心整理-第 18 页,共 23 页 -我们做的差不多了,这最后一步是实际的比较这两个items,并返回一个有用的结果。def py_cm

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁