ctypes --- 用於 Python 的外部函式庫

原始碼:Lib/ctypes


ctypes is a foreign function library for Python. It provides C compatibledata types, and allows calling functions in DLLs or shared libraries. It can beused to wrap these libraries in pure Python.

ctypes 教學

Note: The code samples in this tutorial usedoctest to make sure thatthey actually work. Since some code samples behave differently under Linux,Windows, or macOS, they contain doctest directives in comments.

Note: Some code samples reference the ctypesc_int type. On platformswheresizeof(long)==sizeof(int) it is an alias toc_long.So, you should not be confused ifc_long is printed if you would expectc_int --- they are actually the same type.

Loading dynamic link libraries

ctypes exports thecdll, and on Windowswindll andoledllobjects, for loading dynamic link libraries.

You load libraries by accessing them as attributes of these objects.cdllloads libraries which export functions using the standardcdecl callingconvention, whilewindll libraries call functions using thestdcallcalling convention.oledll also uses thestdcall calling convention, andassumes the functions return a WindowsHRESULT error code. The errorcode is used to automatically raise anOSError exception when thefunction call fails.

在 3.3 版的變更:Windows errors used to raiseWindowsError, which is now an aliasofOSError.

Here are some examples for Windows. Note thatmsvcrt is the MS standard Clibrary containing most standard C functions, and uses thecdecl callingconvention:

>>>fromctypesimport*>>>print(windll.kernel32)<WinDLL 'kernel32', handle ... at ...>>>>print(cdll.msvcrt)<CDLL 'msvcrt', handle ... at ...>>>>libc=cdll.msvcrt>>>

Windows appends the usual.dll file suffix automatically.

備註

Accessing the standard C library throughcdll.msvcrt will use anoutdated version of the library that may be incompatible with the onebeing used by Python. Where possible, use native Python functionality,or else import and use themsvcrt module.

On Linux, it is required to specify the filenameincluding the extension toload a library, so attribute access can not be used to load libraries. Either theLoadLibrary() method of the dll loaders should be used,or you should load the library by creating an instance of CDLL by callingthe constructor:

>>>cdll.LoadLibrary("libc.so.6")<CDLL 'libc.so.6', handle ... at ...>>>>libc=CDLL("libc.so.6")>>>libc<CDLL 'libc.so.6', handle ... at ...>>>>

Accessing functions from loaded dlls

Functions are accessed as attributes of dll objects:

>>>libc.printf<_FuncPtr object at 0x...>>>>print(windll.kernel32.GetModuleHandleA)<_FuncPtr object at 0x...>>>>print(windll.kernel32.MyOwnFunction)Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"ctypes.py", line239, in__getattr__func=_StdcallFuncPtr(name,self)AttributeError:function 'MyOwnFunction' not found>>>

Note that win32 system dlls likekernel32 anduser32 often export ANSIas well as UNICODE versions of a function. The UNICODE version is exported withaW appended to the name, while the ANSI version is exported with anAappended to the name. The win32GetModuleHandle function, which returns amodule handle for a given module name, has the following C prototype, and amacro is used to expose one of them asGetModuleHandle depending on whetherUNICODE is defined or not:

/*ANSI版本*/HMODULEGetModuleHandleA(LPCSTRlpModuleName);/*UNICODE版本*/HMODULEGetModuleHandleW(LPCWSTRlpModuleName);

windll does not try to select one of them by magic, you must access theversion you need by specifyingGetModuleHandleA orGetModuleHandleWexplicitly, and then call it with bytes or string objects respectively.

Sometimes, dlls export functions with names which aren't valid Pythonidentifiers, like"??2@YAPAXI@Z". In this case you have to usegetattr() to retrieve the function:

>>>getattr(cdll.msvcrt,"??2@YAPAXI@Z")<_FuncPtr object at 0x...>>>>

On Windows, some dlls export functions not by name but by ordinal. Thesefunctions can be accessed by indexing the dll object with the ordinal number:

>>>cdll.kernel32[1]<_FuncPtr object at 0x...>>>>cdll.kernel32[0]Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"ctypes.py", line310, in__getitem__func=_StdcallFuncPtr(name,self)AttributeError:function ordinal 0 not found>>>

呼叫函式

You can call these functions like any other Python callable. This example usestherand() function, which takes no arguments and returns a pseudo-random integer:

>>>print(libc.rand())1804289383

On Windows, you can call theGetModuleHandleA() function, which returns a win32 modulehandle (passingNone as single argument to call it with aNULL pointer):

>>>print(hex(windll.kernel32.GetModuleHandleA(None)))0x1d000000>>>

ValueError is raised when you call anstdcall function with thecdecl calling convention, or vice versa:

>>>cdll.kernel32.GetModuleHandleA(None)Traceback (most recent call last):  File"<stdin>", line1, in<module>ValueError:Procedure probably called with not enough arguments (4 bytes missing)>>>>>>windll.msvcrt.printf(b"spam")Traceback (most recent call last):  File"<stdin>", line1, in<module>ValueError:Procedure probably called with too many arguments (4 bytes in excess)>>>

To find out the correct calling convention you have to look into the C headerfile or the documentation for the function you want to call.

On Windows,ctypes uses win32 structured exception handling to preventcrashes from general protection faults when functions are called with invalidargument values:

>>>windll.kernel32.GetModuleHandleA(32)Traceback (most recent call last):  File"<stdin>", line1, in<module>OSError:exception: access violation reading 0x00000020>>>

There are, however, enough ways to crash Python withctypes, so youshould be careful anyway. Thefaulthandler module can be helpful indebugging crashes (e.g. from segmentation faults produced by erroneous C librarycalls).

None, integers, bytes objects and (unicode) strings are the only nativePython objects that can directly be used as parameters in these function calls.None is passed as a CNULL pointer, bytes objects and strings are passedas pointer to the memory block that contains their data (char* orwchar_t*). Python integers are passed as the platform's default Cint type, their value is masked to fit into the C type.

Before we move on calling functions with other parameter types, we have to learnmore aboutctypes data types.

Fundamental data types

ctypes defines a number of primitive C compatible data types:

ctypes 型別

C 型別

Python 型別

c_bool

_Bool

bool (1)

c_char

char

1-character bytes object

c_wchar

wchar_t

1-character string

c_byte

char

int

c_ubyte

unsignedchar

int

c_short

short

int

c_ushort

unsignedshort

int

c_int

int

int

c_uint

unsignedint

int

c_long

long

int

c_ulong

unsignedlong

int

c_longlong

__int64longlong

int

c_ulonglong

unsigned__int64unsignedlonglong

int

c_size_t

size_t

int

c_ssize_t

ssize_tPy_ssize_t

int

c_time_t

time_t

int

c_float

float

float

c_double

double

float

c_longdouble

longdouble

float

c_char_p

char* (NUL terminated)

bytes object orNone

c_wchar_p

wchar_t* (NUL terminated)

字串或None

c_void_p

void*

int orNone

  1. The constructor accepts any object with a truth value.

All these types can be created by calling them with an optional initializer ofthe correct type and value:

>>>c_int()c_long(0)>>>c_wchar_p("Hello, World")c_wchar_p(140018365411392)>>>c_ushort(-3)c_ushort(65533)>>>

Since these types are mutable, their value can also be changed afterwards:

>>>i=c_int(42)>>>print(i)c_long(42)>>>print(i.value)42>>>i.value=-99>>>print(i.value)-99>>>

Assigning a new value to instances of the pointer typesc_char_p,c_wchar_p, andc_void_p changes thememory location theypoint to,not the contents of the memory block (of course not, because Pythonstring objects are immutable):

>>>s="Hello, World">>>c_s=c_wchar_p(s)>>>print(c_s)c_wchar_p(139966785747344)>>>print(c_s.value)Hello World>>>c_s.value="Hi, there">>>print(c_s)# the memory location has changedc_wchar_p(139966783348904)>>>print(c_s.value)Hi, there>>>print(s)# first object is unchangedHello, World>>>

You should be careful, however, not to pass them to functions expecting pointersto mutable memory. If you need mutable memory blocks, ctypes has acreate_string_buffer() function which creates these in various ways. Thecurrent memory block contents can be accessed (or changed) with therawproperty; if you want to access it as NUL terminated string, use thevalueproperty:

>>>fromctypesimport*>>>p=create_string_buffer(3)# create a 3 byte buffer, initialized to NUL bytes>>>print(sizeof(p),repr(p.raw))3 b'\x00\x00\x00'>>>p=create_string_buffer(b"Hello")# create a buffer containing a NUL terminated string>>>print(sizeof(p),repr(p.raw))6 b'Hello\x00'>>>print(repr(p.value))b'Hello'>>>p=create_string_buffer(b"Hello",10)# create a 10 byte buffer>>>print(sizeof(p),repr(p.raw))10 b'Hello\x00\x00\x00\x00\x00'>>>p.value=b"Hi">>>print(sizeof(p),repr(p.raw))10 b'Hi\x00lo\x00\x00\x00\x00\x00'>>>

Thecreate_string_buffer() function replaces the oldc_buffer()function (which is still available as an alias). To create a mutable memoryblock containing unicode characters of the C typewchar_t, use thecreate_unicode_buffer() function.

Calling functions, continued

Note that printf prints to the real standard output channel,not tosys.stdout, so these examples will only work at the console prompt, notfrom withinIDLE orPythonWin:

>>>printf=libc.printf>>>printf(b"Hello,%s\n",b"World!")Hello, World!14>>>printf(b"Hello, %S\n","World!")Hello, World!14>>>printf(b"%d bottles of beer\n",42)42 bottles of beer19>>>printf(b"%f bottles of beer\n",42.5)Traceback (most recent call last):  File"<stdin>", line1, in<module>ctypes.ArgumentError:argument 2: TypeError: Don't know how to convert parameter 2>>>

As has been mentioned before, all Python types except integers, strings, andbytes objects have to be wrapped in their correspondingctypes type, sothat they can be converted to the required C data type:

>>>printf(b"An int%d, a double%f\n",1234,c_double(3.14))An int 1234, a double 3.14000031>>>

Calling variadic functions

On a lot of platforms calling variadic functions through ctypes is exactly the sameas calling functions with a fixed number of parameters. On some platforms, and inparticular ARM64 for Apple Platforms, the calling convention for variadic functionsis different than that for regular functions.

On those platforms it is required to specify theargtypesattribute for the regular, non-variadic, function arguments:

libc.printf.argtypes=[ctypes.c_char_p]

Because specifying the attribute does not inhibit portability it is advised to alwaysspecifyargtypes for all variadic functions.

Calling functions with your own custom data types

You can also customizectypes argument conversion to allow instances ofyour own classes be used as function arguments.ctypes looks for an_as_parameter_ attribute and uses this as the function argument. Theattribute must be an integer, string, bytes, actypes instance, or anobject with an_as_parameter_ attribute:

>>>classBottles:...def__init__(self,number):...self._as_parameter_=number...>>>bottles=Bottles(42)>>>printf(b"%d bottles of beer\n",bottles)42 bottles of beer19>>>

If you don't want to store the instance's data in the_as_parameter_instance variable, you could define aproperty which makes theattribute available on request.

Specifying the required argument types (function prototypes)

It is possible to specify the required argument types of functions exported fromDLLs by setting theargtypes attribute.

argtypes must be a sequence of C data types (theprintf() function isprobably not a good example here, because it takes a variable number anddifferent types of parameters depending on the format string, on the other handthis is quite handy to experiment with this feature):

>>>printf.argtypes=[c_char_p,c_char_p,c_int,c_double]>>>printf(b"String '%s', Int%d, Double%f\n",b"Hi",10,2.2)String 'Hi', Int 10, Double 2.20000037>>>

Specifying a format protects against incompatible argument types (just as aprototype for a C function), and tries to convert the arguments to valid types:

>>>printf(b"%d%d%d",1,2,3)Traceback (most recent call last):  File"<stdin>", line1, in<module>ctypes.ArgumentError:argument 2: TypeError: 'int' object cannot be interpreted as ctypes.c_char_p>>>printf(b"%s%d%f\n",b"X",2,3)X 2 3.00000013>>>

If you have defined your own classes which you pass to function calls, you haveto implement afrom_param() class method for them to be able to use themin theargtypes sequence. Thefrom_param() class method receivesthe Python object passed to the function call, it should do a typecheck orwhatever is needed to make sure this object is acceptable, and then return theobject itself, its_as_parameter_ attribute, or whatever you want topass as the C function argument in this case. Again, the result should be aninteger, string, bytes, actypes instance, or an object with an_as_parameter_ attribute.

Return types

By default functions are assumed to return the Cint type. Otherreturn types can be specified by setting therestype attribute of thefunction object.

The C prototype oftime() istime_ttime(time_t*). Becausetime_tmight be of a different type than the default return typeint, you shouldspecify therestype attribute:

>>>libc.time.restype=c_time_t

The argument types can be specified usingargtypes:

>>>libc.time.argtypes=(POINTER(c_time_t),)

To call the function with aNULL pointer as first argument, useNone:

>>>print(libc.time(None))1150640792

Here is a more advanced example, it uses thestrchr() function, which expectsa string pointer and a char, and returns a pointer to a string:

>>>strchr=libc.strchr>>>strchr(b"abcdef",ord("d"))8059983>>>strchr.restype=c_char_p# c_char_p is a pointer to a string>>>strchr(b"abcdef",ord("d"))b'def'>>>print(strchr(b"abcdef",ord("x")))None>>>

If you want to avoid theord("x") calls above, you can set theargtypes attribute, and the second argument will be converted from asingle character Python bytes object into a C char:

>>>strchr.restype=c_char_p>>>strchr.argtypes=[c_char_p,c_char]>>>strchr(b"abcdef",b"d")b'def'>>>strchr(b"abcdef",b"def")Traceback (most recent call last):ctypes.ArgumentError:argument 2: TypeError: one character bytes, bytearray or integer expected>>>print(strchr(b"abcdef",b"x"))None>>>strchr(b"abcdef",b"d")b'def'>>>

You can also use a callable Python object (a function or a class for example) astherestype attribute, if the foreign function returns an integer. Thecallable will be called with theinteger the C function returns, and theresult of this call will be used as the result of your function call. This isuseful to check for error return values and automatically raise an exception:

>>>GetModuleHandle=windll.kernel32.GetModuleHandleA>>>defValidHandle(value):...ifvalue==0:...raiseWinError()...returnvalue...>>>>>>GetModuleHandle.restype=ValidHandle>>>GetModuleHandle(None)486539264>>>GetModuleHandle("something silly")Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"<stdin>", line3, inValidHandleOSError:[Errno 126] The specified module could not be found.>>>

WinError is a function which will call WindowsFormatMessage() api toget the string representation of an error code, andreturns an exception.WinError takes an optional error code parameter, if no one is used, it callsGetLastError() to retrieve it.

Please note that a much more powerful error checking mechanism is availablethrough theerrcheck attribute;see the reference manual for details.

Passing pointers (or: passing parameters by reference)

Sometimes a C api function expects apointer to a data type as parameter,probably to write into the corresponding location, or if the data is too largeto be passed by value. This is also known aspassing parameters by reference.

ctypes exports thebyref() function which is used to pass parametersby reference. The same effect can be achieved with thepointer() function,althoughpointer() does a lot more work since it constructs a real pointerobject, so it is faster to usebyref() if you don't need the pointerobject in Python itself:

>>>i=c_int()>>>f=c_float()>>>s=create_string_buffer(b'\000'*32)>>>print(i.value,f.value,repr(s.value))0 0.0 b''>>>libc.sscanf(b"1 3.14 Hello",b"%d%f%s",...byref(i),byref(f),s)3>>>print(i.value,f.value,repr(s.value))1 3.1400001049 b'Hello'>>>

Structures and unions

Structures and unions must derive from theStructure andUnionbase classes which are defined in thectypes module. Each subclass mustdefine a_fields_ attribute._fields_ must be a list of2-tuples, containing afield name and afield type.

The field type must be actypes type likec_int, or any otherderivedctypes type: structure, union, array, pointer.

Here is a simple example of a POINT structure, which contains two integers namedx andy, and also shows how to initialize a structure in the constructor:

>>>fromctypesimport*>>>classPOINT(Structure):..._fields_=[("x",c_int),...("y",c_int)]...>>>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"<stdin>", line1, in<module>TypeError:too many initializers>>>

You can, however, build much more complicated structures. A structure canitself contain other structures by using a structure as a field type.

Here is a RECT structure which contains two POINTs namedupperleft andlowerright:

>>>classRECT(Structure):..._fields_=[("upperleft",POINT),...("lowerright",POINT)]...>>>rc=RECT(point)>>>print(rc.upperleft.x,rc.upperleft.y)0 5>>>print(rc.lowerright.x,rc.lowerright.y)0 0>>>

Nested structures can also be initialized in the constructor in several ways:

>>>r=RECT(POINT(1,2),POINT(3,4))>>>r=RECT((1,2),(3,4))

Fielddescriptors can be retrieved from theclass, they are usefulfor debugging because they can provide useful information:

>>>print(POINT.x)<Field type=c_long, ofs=0, size=4>>>>print(POINT.y)<Field type=c_long, ofs=4, size=4>>>>

警告

ctypes does not support passing unions or structures with bit-fieldsto functions by value. While this may work on 32-bit x86, it's notguaranteed by the library to work in the general case. Unions andstructures with bit-fields should always be passed to functions by pointer.

Structure/union alignment and byte order

By default, Structure and Union fields are aligned in the same way the Ccompiler does it. It is possible to override this behavior by specifying a_pack_ class attribute in the subclass definition.This must be set to a positive integer and specifies the maximum alignment for the fields.This is what#pragmapack(n) also does in MSVC.It is also possible to set a minimum alignment for how the subclass itself is packed in thesame way#pragmaalign(n) works in MSVC.This can be achieved by specifying a_align_ class attributein the subclass definition.

ctypes uses the native byte order for Structures and Unions. To buildstructures with non-native byte order, you can use one of theBigEndianStructure,LittleEndianStructure,BigEndianUnion, andLittleEndianUnion base classes. Theseclasses cannot contain pointer fields.

Bit fields in structures and unions

It is possible to create structures and unions containing bit fields. Bit fieldsare only possible for integer fields, the bit width is specified as the thirditem in the_fields_ tuples:

>>>classInt(Structure):..._fields_=[("first_16",c_int,16),...("second_16",c_int,16)]...>>>print(Int.first_16)<Field type=c_long, ofs=0:0, bits=16>>>>print(Int.second_16)<Field type=c_long, ofs=0:16, bits=16>>>>

Arrays

Arrays are sequences, containing a fixed number of instances of the same type.

The recommended way to create array types is by multiplying a data type with apositive integer:

TenPointsArrayType=POINT*10

Here is an example of a somewhat artificial data type, a structure containing 4POINTs among other stuff:

>>>fromctypesimport*>>>classPOINT(Structure):..._fields_=("x",c_int),("y",c_int)...>>>classMyStruct(Structure):..._fields_=[("a",c_int),...("b",c_float),...("point_array",POINT*4)]>>>>>>print(len(MyStruct().point_array))4>>>

Instances are created in the usual way, by calling the class:

arr=TenPointsArrayType()forptinarr:print(pt.x,pt.y)

The above code print a series of00 lines, because the array contents isinitialized to zeros.

Initializers of the correct type can also be specified:

>>>fromctypesimport*>>>TenIntegers=c_int*10>>>ii=TenIntegers(1,2,3,4,5,6,7,8,9,10)>>>print(ii)<c_long_Array_10 object at 0x...>>>>foriinii:print(i,end=" ")...1 2 3 4 5 6 7 8 9 10>>>

Pointers

Pointer instances are created by calling thepointer() function on actypes type:

>>>fromctypesimport*>>>i=c_int(42)>>>pi=pointer(i)>>>

Pointer instances have acontents attribute whichreturns the object to which the pointer points, thei object above:

>>>pi.contentsc_long(42)>>>

Note thatctypes does not have OOR (original object return), it constructs anew, equivalent object each time you retrieve an attribute:

>>>pi.contentsisiFalse>>>pi.contentsispi.contentsFalse>>>

Assigning anotherc_int instance to the pointer's contents attributewould cause the pointer to point to the memory location where this is stored:

>>>i=c_int(99)>>>pi.contents=i>>>pi.contentsc_long(99)>>>

Pointer instances can also be indexed with integers:

>>>pi[0]99>>>

Assigning to an integer index changes the pointed to value:

>>>print(i)c_long(99)>>>pi[0]=22>>>print(i)c_long(22)>>>

It is also possible to use indexes different from 0, but you must know whatyou're doing, just as in C: You can access or change arbitrary memory locations.Generally you only use this feature if you receive a pointer from a C function,and youknow that the pointer actually points to an array instead of a singleitem.

Behind the scenes, thepointer() function does more than simply createpointer instances, it has to create pointertypes first. This is done with thePOINTER() function, which accepts anyctypes type, and returns anew type:

>>>PI=POINTER(c_int)>>>PI<class 'ctypes.LP_c_long'>>>>PI(42)Traceback (most recent call last):  File"<stdin>", line1, in<module>TypeError:expected c_long instead of int>>>PI(c_int(42))<ctypes.LP_c_long object at 0x...>>>>

Calling the pointer type without an argument creates aNULL pointer.NULL pointers have aFalse boolean value:

>>>null_ptr=POINTER(c_int)()>>>print(bool(null_ptr))False>>>

ctypes checks forNULL when dereferencing pointers (but dereferencinginvalid non-NULL pointers would crash Python):

>>>null_ptr[0]Traceback (most recent call last):....ValueError:NULL pointer access>>>>>>null_ptr[0]=1234Traceback (most recent call last):....ValueError:NULL pointer access>>>

Type conversions

Usually, ctypes does strict type checking. This means, if you havePOINTER(c_int) in theargtypes list of a function or as the type ofa member field in a structure definition, only instances of exactly the sametype are accepted. There are some exceptions to this rule, where ctypes acceptsother objects. For example, you can pass compatible array instances instead ofpointer types. So, forPOINTER(c_int), ctypes accepts an array of c_int:

>>>classBar(Structure):..._fields_=[("count",c_int),("values",POINTER(c_int))]...>>>bar=Bar()>>>bar.values=(c_int*3)(1,2,3)>>>bar.count=3>>>foriinrange(bar.count):...print(bar.values[i])...123>>>

In addition, if a function argument is explicitly declared to be a pointer type(such asPOINTER(c_int)) inargtypes, an object of the pointedtype (c_int in this case) can be passed to the function. ctypes will applythe requiredbyref() conversion in this case automatically.

To set a POINTER type field toNULL, you can assignNone:

>>>bar.values=None>>>

Sometimes you have instances of incompatible types. In C, you can cast one typeinto another type.ctypes provides acast() function which can beused in the same way. TheBar structure defined above acceptsPOINTER(c_int) pointers orc_int arrays for itsvalues field,but not instances of other types:

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

For these cases, thecast() function is handy.

Thecast() function can be used to cast a ctypes instance into a pointerto a different ctypes data type.cast() takes two parameters, a ctypesobject that is or can be converted to a pointer of some kind, and a ctypespointer type. It returns an instance of the second argument, which referencesthe same memory block as the first argument:

>>>a=(c_byte*4)()>>>cast(a,POINTER(c_int))<ctypes.LP_c_long object at ...>>>>

So,cast() can be used to assign to thevalues field ofBar thestructure:

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

Incomplete Types

Incomplete Types are structures, unions or arrays whose members are not yetspecified. In C, they are specified by forward declarations, which are definedlater:

structcell;/*forwarddeclaration*/structcell{char*name;structcell*next;};

The straightforward translation into ctypes code would be this, but it does notwork:

>>>classcell(Structure):..._fields_=[("name",c_char_p),...("next",POINTER(cell))]...Traceback (most recent call last):  File"<stdin>", line1, in<module>  File"<stdin>", line2, incellNameError:name 'cell' is not defined>>>

because the newclasscell is not available in the class statement itself.Inctypes, we can define thecell class and set the_fields_ attribute later, after the class statement:

>>>fromctypesimport*>>>classcell(Structure):...pass...>>>cell._fields_=[("name",c_char_p),...("next",POINTER(cell))]>>>

Let's try it. We create two instances ofcell, and let them point to eachother, and finally follow the pointer chain a few times:

>>>c1=cell()>>>c1.name=b"foo">>>c2=cell()>>>c2.name=b"bar">>>c1.next=pointer(c2)>>>c2.next=pointer(c1)>>>p=c1>>>foriinrange(8):...print(p.name,end=" ")...p=p.next[0]...foo bar foo bar foo bar foo bar>>>

回呼函式

ctypes allows creating C callable function pointers from Python callables.These are sometimes calledcallback functions.

First, you must create a class for the callback function. The class knows thecalling convention, the return type, and the number and types of arguments thisfunction will receive.

TheCFUNCTYPE() factory function creates types for callback functionsusing thecdecl calling convention. On Windows, theWINFUNCTYPE()factory function creates types for callback functions using thestdcallcalling convention.

Both of these factory functions are called with the result type as firstargument, and the callback functions expected argument types as the remainingarguments.

I will present an example here which uses the standard C library'sqsort() function, that is used to sort items with the help of a callbackfunction.qsort() will be used to sort an array of integers:

>>>IntArray5=c_int*5>>>ia=IntArray5(5,1,7,33,99)>>>qsort=libc.qsort>>>qsort.restype=None>>>

qsort() must be called with a pointer to the data to sort, the number ofitems in the data array, the size of one item, and a pointer to the comparisonfunction, the callback. The callback will then be called with two pointers toitems, and it must return a negative integer if the first item is smaller thanthe second, a zero if they are equal, and a positive integer otherwise.

So our callback function receives pointers to integers, and must return aninteger. First we create thetype for the callback function:

>>>CMPFUNC=CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int))>>>

To get started, here is a simple callback that shows the values it getspassed:

>>>defpy_cmp_func(a,b):...print("py_cmp_func",a[0],b[0])...return0...>>>cmp_func=CMPFUNC(py_cmp_func)>>>

結果為:

>>>qsort(ia,len(ia),sizeof(c_int),cmp_func)py_cmp_func 5 1py_cmp_func 33 99py_cmp_func 7 33py_cmp_func 5 7py_cmp_func 1 7>>>

Now we can actually compare the two items and return a useful result:

>>>defpy_cmp_func(a,b):...print("py_cmp_func",a[0],b[0])...returna[0]-b[0]...>>>>>>qsort(ia,len(ia),sizeof(c_int),CMPFUNC(py_cmp_func))py_cmp_func 5 1py_cmp_func 33 99py_cmp_func 7 33py_cmp_func 1 7py_cmp_func 5 7>>>

As we can easily check, our array is sorted now:

>>>foriinia:print(i,end=" ")...1 5 7 33 99>>>

The function factories can be used as decorator factories, so we may as wellwrite:

>>>@CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int))...defpy_cmp_func(a,b):...print("py_cmp_func",a[0],b[0])...returna[0]-b[0]...>>>qsort(ia,len(ia),sizeof(c_int),py_cmp_func)py_cmp_func 5 1py_cmp_func 33 99py_cmp_func 7 33py_cmp_func 1 7py_cmp_func 5 7>>>

備註

Make sure you keep references toCFUNCTYPE() objects as long as theyare used from C code.ctypes doesn't, and if you don't, they may begarbage collected, crashing your program when a callback is made.

Also, note that if the callback function is called in a thread createdoutside of Python's control (e.g. by the foreign code that calls thecallback), ctypes creates a new dummy Python thread on every invocation. Thisbehavior is correct for most purposes, but it means that values stored withthreading.local willnot survive across different callbacks, even whenthose calls are made from the same C thread.

Accessing values exported from dlls

Some shared libraries not only export functions, they also export variables. Anexample in the Python library itself is thePy_Version, Pythonruntime version number encoded in a single constant integer.

ctypes can access values like this with thein_dll() class methods ofthe type.pythonapi is a predefined symbol giving access to the Python Capi:

>>>version=ctypes.c_int.in_dll(ctypes.pythonapi,"Py_Version")>>>print(hex(version.value))0x30c00a0

An extended example which also demonstrates the use of pointers accesses thePyImport_FrozenModules pointer exported by Python.

Quoting the docs for that value:

This pointer is initialized to point to an array of_frozenrecords, terminated by one whose members are allNULL or zero. When a frozenmodule is imported, it is searched in this table. Third-party code could playtricks with this to provide a dynamically created collection of frozen modules.

So manipulating this pointer could even prove useful. To restrict the examplesize, we show only how this table can be read withctypes:

>>>fromctypesimport*>>>>>>classstruct_frozen(Structure):..._fields_=[("name",c_char_p),...("code",POINTER(c_ubyte)),...("size",c_int),...("get_code",POINTER(c_ubyte)),# 函式指標...]...>>>

We have defined the_frozen data type, so we can get the pointerto the table:

>>>FrozenTable=POINTER(struct_frozen)>>>table=FrozenTable.in_dll(pythonapi,"_PyImport_FrozenBootstrap")>>>

Sincetable is apointer to the array ofstruct_frozen records, wecan iterate over it, but we just have to make sure that our loop terminates,because pointers have no size. Sooner or later it would probably crash with anaccess violation or whatever, so it's better to break out of the loop when wehit theNULL entry:

>>>foritemintable:...ifitem.nameisNone:...break...print(item.name.decode("ascii"),item.size)..._frozen_importlib 31764_frozen_importlib_external 41499zipimport 12345>>>

The fact that standard Python has a frozen module and a frozen package(indicated by the negativesize member) is not well known, it is only usedfor testing. Try it out withimport__hello__ for example.

Surprises

There are some edges inctypes where you might expect something otherthan what actually happens.

Consider the following example:

>>>fromctypesimport*>>>classPOINT(Structure):..._fields_=("x",c_int),("y",c_int)...>>>classRECT(Structure):..._fields_=("a",POINT),("b",POINT)...>>>p1=POINT(1,2)>>>p2=POINT(3,4)>>>rc=RECT(p1,p2)>>>print(rc.a.x,rc.a.y,rc.b.x,rc.b.y)1 2 3 4>>># now swap the two points>>>rc.a,rc.b=rc.b,rc.a>>>print(rc.a.x,rc.a.y,rc.b.x,rc.b.y)3 4 3 4>>>

Hm. We certainly expected the last statement to print3412. Whathappened? Here are the steps of therc.a,rc.b=rc.b,rc.a line above:

>>>temp0,temp1=rc.b,rc.a>>>rc.a=temp0>>>rc.b=temp1>>>

Note thattemp0 andtemp1 are objects still using the internal buffer oftherc object above. So executingrc.a=temp0 copies the buffercontents oftemp0 intorc 's buffer. This, in turn, changes thecontents oftemp1. So, the last assignmentrc.b=temp1, doesn't havethe expected effect.

Keep in mind that retrieving sub-objects from Structure, Unions, and Arraysdoesn'tcopy the sub-object, instead it retrieves a wrapper object accessingthe root-object's underlying buffer.

Another example that may behave differently from what one would expect is this:

>>>s=c_char_p()>>>s.value=b"abc def ghi">>>s.valueb'abc def ghi'>>>s.valueiss.valueFalse>>>

備註

Objects instantiated fromc_char_p can only have their value set to bytesor integers.

Why is it printingFalse? ctypes instances are objects containing a memoryblock plus somedescriptors accessing the contents of the memory.Storing a Python object in the memory block does not store the object itself,instead thecontents of the object is stored. Accessing the contents againconstructs a new Python object each time!

Variable-sized data types

ctypes provides some support for variable-sized arrays and structures.

Theresize() function can be used to resize the memory buffer of anexisting ctypes object. The function takes the object as first argument, andthe requested size in bytes as the second argument. The memory block cannot bemade smaller than the natural memory block specified by the objects type, aValueError is raised if this is tried:

>>>short_array=(c_short*4)()>>>print(sizeof(short_array))8>>>resize(short_array,4)Traceback (most recent call last):...ValueError:minimum size is 8>>>resize(short_array,32)>>>sizeof(short_array)32>>>sizeof(type(short_array))8>>>

This is nice and fine, but how would one access the additional elementscontained in this array? Since the type still only knows about 4 elements, weget errors accessing other elements:

>>>short_array[:][0, 0, 0, 0]>>>short_array[7]Traceback (most recent call last):...IndexError:invalid index>>>

Another way to use variable-sized data types withctypes is to use thedynamic nature of Python, and (re-)define the data type after the required sizeis already known, on a case by case basis.

ctypes reference

Finding shared libraries

When programming in a compiled language, shared libraries are accessed whencompiling/linking a program, and when the program is run.

The purpose of thefind_library() function is to locate a library in a waysimilar to what the compiler or runtime loader does (on platforms with severalversions of a shared library the most recent should be loaded), while the ctypeslibrary loaders act like when a program is run, and call the runtime loaderdirectly.

Thectypes.util module provides a function which can help to determinethe library to load.

ctypes.util.find_library(name)

Try to find a library and return a pathname.name is the library name withoutany prefix likelib, suffix like.so,.dylib or version number (thisis the form used for the posix linker option-l). If no library canbe found, returnsNone.

The exact functionality is system dependent.

On Linux,find_library() tries to run external programs(/sbin/ldconfig,gcc,objdump andld) to find the library file.It returns the filename of the library file.

在 3.6 版的變更:On Linux, the value of the environment variableLD_LIBRARY_PATH is usedwhen searching for libraries, if a library cannot be found by any other means.

以下是一些範例:

>>>fromctypes.utilimportfind_library>>>find_library("m")'libm.so.6'>>>find_library("c")'libc.so.6'>>>find_library("bz2")'libbz2.so.1.0'>>>

On macOS and Android,find_library() uses the system'sstandard naming schemes and paths to locate the library, and returns a fullpathname if successful:

>>>fromctypes.utilimportfind_library>>>find_library("c")'/usr/lib/libc.dylib'>>>find_library("m")'/usr/lib/libm.dylib'>>>find_library("bz2")'/usr/lib/libbz2.dylib'>>>find_library("AGL")'/System/Library/Frameworks/AGL.framework/AGL'>>>

On Windows,find_library() searches along the system search path, andreturns the full pathname, but since there is no predefined naming scheme a calllikefind_library("c") will fail and returnNone.

If wrapping a shared library withctypes, itmay be better to determinethe shared library name at development time, and hardcode that into the wrappermodule instead of usingfind_library() to locate the library at runtime.

Loading shared libraries

There are several ways to load shared libraries into the Python process. Oneway is to instantiate one of the following classes:

classctypes.CDLL(name,mode=DEFAULT_MODE,handle=None,use_errno=False,use_last_error=False,winmode=None)

Instances of this class represent loaded shared libraries. Functions in theselibraries use the standard C calling convention, and are assumed to returnint.

On Windows creating aCDLL instance may fail even if the DLL nameexists. When a dependent DLL of the loaded DLL is not found, aOSError error is raised with the message"[WinError 126] Thespecified module could not be found". This error message does not containthe name of the missing DLL because the Windows API does not return thisinformation making this error hard to diagnose. To resolve this error anddetermine which DLL is not found, you need to find the list of dependentDLLs and determine which one is not found using Windows debugging andtracing tools.

在 3.12 版的變更:Thename parameter can now be apath-like object.

也參考

Microsoft DUMPBIN tool-- A tool to find DLL dependents.

classctypes.OleDLL(name,mode=DEFAULT_MODE,handle=None,use_errno=False,use_last_error=False,winmode=None)

Instances of this class represent loaded shared libraries,functions in these libraries use thestdcall calling convention, and areassumed to return the windows specificHRESULT code.HRESULTvalues contain information specifying whether the function call failed orsucceeded, together with additional error code. If the return value signals afailure, anOSError is automatically raised.

適用: Windows

在 3.3 版的變更:WindowsError used to be raised,which is now an alias ofOSError.

在 3.12 版的變更:Thename parameter can now be apath-like object.

classctypes.WinDLL(name,mode=DEFAULT_MODE,handle=None,use_errno=False,use_last_error=False,winmode=None)

Instances of this class represent loaded shared libraries,functions in these libraries use thestdcall calling convention, and areassumed to returnint by default.

適用: Windows

在 3.12 版的變更:Thename parameter can now be apath-like object.

The Pythonglobal interpreter lock is released before calling anyfunction exported by these libraries, and reacquired afterwards.

classctypes.PyDLL(name,mode=DEFAULT_MODE,handle=None)

Instances of this class behave likeCDLL instances, except that thePython GIL isnot released during the function call, and after the functionexecution the Python error flag is checked. If the error flag is set, a Pythonexception is raised.

Thus, this is only useful to call Python C api functions directly.

在 3.12 版的變更:Thename parameter can now be apath-like object.

All these classes can be instantiated by calling them with at least oneargument, the pathname of the shared library. If you have an existing handle toan already loaded shared library, it can be passed as thehandle namedparameter, otherwise the underlying platform'sdlopen() orLoadLibrary() function is used to load the library intothe process, and to get a handle to it.

Themode parameter can be used to specify how the library is loaded. Fordetails, consult thedlopen(3) manpage. On Windows,mode isignored. On posix systems, RTLD_NOW is always added, and is notconfigurable.

Theuse_errno parameter, when set to true, enables a ctypes mechanism thatallows accessing the systemerrno error number in a safe way.ctypes maintains a thread-local copy of the system'serrnovariable; if you call foreign functions created withuse_errno=True then theerrno value before the function call is swapped with the ctypes privatecopy, the same happens immediately after the function call.

The functionctypes.get_errno() returns the value of the ctypes privatecopy, and the functionctypes.set_errno() changes the ctypes private copyto a new value and returns the former value.

Theuse_last_error parameter, when set to true, enables the same mechanism forthe Windows error code which is managed by theGetLastError() andSetLastError() Windows API functions;ctypes.get_last_error() andctypes.set_last_error() are used to request and change the ctypes privatecopy of the windows error code.

Thewinmode parameter is used on Windows to specify how the library is loaded(sincemode is ignored). It takes any value that is valid for the Win32 APILoadLibraryEx flags parameter. When omitted, the default is to use theflags that result in the most secure DLL load, which avoids issues such as DLLhijacking. Passing the full path to the DLL is the safest way to ensure thecorrect library and dependencies are loaded.

在 3.8 版的變更:新增winmode 參數。

ctypes.RTLD_GLOBAL

Flag to use asmode parameter. On platforms where this flag is not available,it is defined as the integer zero.

ctypes.RTLD_LOCAL

Flag to use asmode parameter. On platforms where this is not available, itis the same asRTLD_GLOBAL.

ctypes.DEFAULT_MODE

The default mode which is used to load shared libraries. On OSX 10.3, this isRTLD_GLOBAL, otherwise it is the same asRTLD_LOCAL.

Instances of these classes have no public methods. Functions exported by theshared library can be accessed as attributes or by index. Please note thataccessing the function through an attribute caches the result and thereforeaccessing it repeatedly returns the same object each time. On the other hand,accessing it through an index returns a new object each time:

>>>fromctypesimportCDLL>>>libc=CDLL("libc.so.6")# 於 Linux>>>libc.time==libc.timeTrue>>>libc['time']==libc['time']False

The following public attributes are available, their name starts with anunderscore to not clash with exported function names:

PyDLL._handle

The system handle used to access the library.

PyDLL._name

The name of the library passed in the constructor.

Shared libraries can also be loaded by using one of the prefabricated objects,which are instances of theLibraryLoader class, either by calling theLoadLibrary() method, or by retrieving the library asattribute of the loader instance.

classctypes.LibraryLoader(dlltype)

Class which loads shared libraries.dlltype should be one of theCDLL,PyDLL,WinDLL, orOleDLL types.

__getattr__() has special behavior: It allows loading a shared library byaccessing it as attribute of a library loader instance. The result is cached,so repeated attribute accesses return the same library each time.

LoadLibrary(name)

Load a shared library into the process and return it. This method alwaysreturns a new instance of the library.

These prefabricated library loaders are available:

ctypes.cdll

CreatesCDLL instances.

ctypes.windll

CreatesWinDLL instances.

適用: Windows

ctypes.oledll

CreatesOleDLL instances.

適用: Windows

ctypes.pydll

CreatesPyDLL instances.

For accessing the C Python api directly, a ready-to-use Python shared libraryobject is available:

ctypes.pythonapi

An instance ofPyDLL that exposes Python C API functions asattributes. Note that all these functions are assumed to return Cint, which is of course not always the truth, so you have to assignthe correctrestype attribute to use these functions.

Loading a library through any of these objects raises anauditing eventctypes.dlopen with string argumentname, the name used to load the library.

Accessing a function on a loaded library raises an auditing eventctypes.dlsym with argumentslibrary (the library object) andname(the symbol's name as a string or integer).

In cases when only the library handle is available rather than the object,accessing a function raises an auditing eventctypes.dlsym/handle withargumentshandle (the raw library handle) andname.

Foreign functions

As explained in the previous section, foreign functions can be accessed asattributes of loaded shared libraries. The function objects created in this wayby default accept any number of arguments, accept any ctypes data instances asarguments, and return the default result type specified by the library loader.

They are instances of a private local class_FuncPtr (not exposedinctypes) which inherits from the private_CFuncPtr class:

>>>importctypes>>>lib=ctypes.CDLL(None)>>>issubclass(lib._FuncPtr,ctypes._CFuncPtr)True>>>lib._FuncPtrisctypes._CFuncPtrFalse
classctypes._CFuncPtr

Base class for C callable foreign functions.

Instances of foreign functions are also C compatible data types; theyrepresent C function pointers.

This behavior can be customized by assigning to special attributes of theforeign function object.

restype

Assign a ctypes type to specify the result type of the foreign function.UseNone forvoid, a function not returning anything.

It is possible to assign a callable Python object that is not a ctypestype, in this case the function is assumed to return a Cint, andthe callable will be called with this integer, allowing furtherprocessing or error checking. Using this is deprecated, for more flexiblepost processing or error checking use a ctypes data type asrestype and assign a callable to theerrcheck attribute.

argtypes

Assign a tuple of ctypes types to specify the argument types that thefunction accepts. Functions using thestdcall calling convention canonly be called with the same number of arguments as the length of thistuple; functions using the C calling convention accept additional,unspecified arguments as well.

When a foreign function is called, each actual argument is passed to thefrom_param() class method of the items in theargtypestuple, this method allows adapting the actual argument to an object thatthe foreign function accepts. For example, ac_char_p item intheargtypes tuple will convert a string passed as argument intoa bytes object using ctypes conversion rules.

New: It is now possible to put items in argtypes which are not ctypestypes, but each item must have afrom_param() method which returns avalue usable as argument (integer, string, ctypes instance). This allowsdefining adapters that can adapt custom objects as function parameters.

errcheck

Assign a Python function or another callable to this attribute. Thecallable will be called with three or more arguments:

callable(result,func,arguments)

result is what the foreign function returns, as specified by therestype attribute.

func is the foreign function object itself, this allows reusing thesame callable object to check or post process the results of severalfunctions.

arguments is a tuple containing the parameters originally passed tothe function call, this allows specializing the behavior on thearguments used.

The object that this function returns will be returned from theforeign function call, but it can also check the result valueand raise an exception if the foreign function call failed.

exceptionctypes.ArgumentError

This exception is raised when a foreign function call cannot convert one of thepassed arguments.

On Windows, when a foreign function call raises a system exception (forexample, due to an access violation), it will be captured and replaced witha suitable Python exception. Further, an auditing eventctypes.set_exception with argumentcode will be raised, allowing anaudit hook to replace the exception with its own.

Some ways to invoke foreign function calls may raise an auditing eventctypes.call_function with argumentsfunctionpointer andarguments.

Function prototypes

Foreign functions can also be created by instantiating function prototypes.Function prototypes are similar to function prototypes in C; they describe afunction (return type, argument types, calling convention) without defining animplementation. The factory functions must be called with the desired resulttype and the argument types of the function, and can be used as decoratorfactories, and as such, be applied to functions through the@wrapper syntax.See回呼函式 for examples.

ctypes.CFUNCTYPE(restype,*argtypes,use_errno=False,use_last_error=False)

The returned function prototype creates functions that use the standard Ccalling convention. The function will release the GIL during the call. Ifuse_errno is set to true, the ctypes private copy of the systemerrno variable is exchanged with the realerrno value beforeand after the call;use_last_error does the same for the Windows errorcode.

ctypes.WINFUNCTYPE(restype,*argtypes,use_errno=False,use_last_error=False)

The returned function prototype creates functions that use thestdcall calling convention. The function willrelease the GIL during the call.use_errno anduse_last_error have thesame meaning as above.

適用: Windows

ctypes.PYFUNCTYPE(restype,*argtypes)

The returned function prototype creates functions that use the Python callingconvention. The function willnot release the GIL during the call.

Function prototypes created by these factory functions can be instantiated indifferent ways, depending on the type and number of the parameters in the call:

prototype(address)

Returns a foreign function at the specified address which must be an integer.

prototype(callable)

Create a C callable function (a callback function) from a Pythoncallable.

prototype(func_spec[,paramflags])

Returns a foreign function exported by a shared library.func_spec mustbe a 2-tuple(name_or_ordinal,library). The first item is the name ofthe exported function as string, or the ordinal of the exported functionas small integer. The second item is the shared library instance.

prototype(vtbl_index,name[,paramflags[,iid]])

Returns a foreign function that will call a COM method.vtbl_index isthe index into the virtual function table, a small non-negativeinteger.name is name of the COM method.iid is an optional pointer tothe interface identifier which is used in extended error reporting.

COM methods use a special calling convention: They require a pointer tothe COM interface as first argument, in addition to those parameters thatare specified in theargtypes tuple.

The optionalparamflags parameter creates foreign function wrappers with muchmore functionality than the features described above.

paramflags must be a tuple of the same length asargtypes.

Each item in this tuple contains further information about a parameter, it mustbe a tuple containing one, two, or three items.

The first item is an integer containing a combination of directionflags for the parameter:

1

Specifies an input parameter to the function.

2

Output parameter. The foreign function fills in a value.

4

Input parameter which defaults to the integer zero.

The optional second item is the parameter name as string. If this is specified,the foreign function can be called with named parameters.

The optional third item is the default value for this parameter.

The following example demonstrates how to wrap the WindowsMessageBoxW function sothat it supports default parameters and named arguments. The C declaration fromthe windows header file is this:

WINUSERAPIintWINAPIMessageBoxW(HWNDhWnd,LPCWSTRlpText,LPCWSTRlpCaption,UINTuType);

Here is the wrapping withctypes:

>>>fromctypesimportc_int,WINFUNCTYPE,windll>>>fromctypes.wintypesimportHWND,LPCWSTR,UINT>>>prototype=WINFUNCTYPE(c_int,HWND,LPCWSTR,LPCWSTR,UINT)>>>paramflags=(1,"hwnd",0),(1,"text","Hi"),(1,"caption","Hello from ctypes"),(1,"flags",0)>>>MessageBox=prototype(("MessageBoxW",windll.user32),paramflags)

TheMessageBox foreign function can now be called in these ways:

>>>MessageBox()>>>MessageBox(text="Spam, spam, spam")>>>MessageBox(flags=2,text="foo bar")

A second example demonstrates output parameters. The win32GetWindowRectfunction retrieves the dimensions of a specified window by copying them intoRECT structure that the caller has to supply. Here is the C declaration:

WINUSERAPIBOOLWINAPIGetWindowRect(HWNDhWnd,LPRECTlpRect);

Here is the wrapping withctypes:

>>>fromctypesimportPOINTER,WINFUNCTYPE,windll,WinError>>>fromctypes.wintypesimportBOOL,HWND,RECT>>>prototype=WINFUNCTYPE(BOOL,HWND,POINTER(RECT))>>>paramflags=(1,"hwnd"),(2,"lprect")>>>GetWindowRect=prototype(("GetWindowRect",windll.user32),paramflags)>>>

Functions with output parameters will automatically return the output parametervalue if there is a single one, or a tuple containing the output parametervalues when there are more than one, so the GetWindowRect function now returns aRECT instance, when called.

Output parameters can be combined with theerrcheck protocol to dofurther output processing and error checking. The win32GetWindowRect apifunction returns aBOOL to signal success or failure, so this function coulddo the error checking, and raises an exception when the api call failed:

>>>deferrcheck(result,func,args):...ifnotresult:...raiseWinError()...returnargs...>>>GetWindowRect.errcheck=errcheck>>>

If theerrcheck function returns the argument tuple it receivesunchanged,ctypes continues the normal processing it does on the outputparameters. If you want to return a tuple of window coordinates instead of aRECT instance, you can retrieve the fields in the function and return theminstead, the normal processing will no longer take place:

>>>deferrcheck(result,func,args):...ifnotresult:...raiseWinError()...rc=args[1]...returnrc.left,rc.top,rc.bottom,rc.right...>>>GetWindowRect.errcheck=errcheck>>>

Utility functions

ctypes.addressof(obj)

Returns the address of the memory buffer as integer.obj must be aninstance of a ctypes type.

引發一個附帶引數obj稽核事件ctypes.addressof

ctypes.alignment(obj_or_type)

Returns the alignment requirements of a ctypes type.obj_or_type must be actypes type or instance.

ctypes.byref(obj[,offset])

Returns a light-weight pointer toobj, which must be an instance of actypes type.offset defaults to zero, and must be an integer that will beadded to the internal pointer value.

byref(obj,offset) corresponds to this C code:

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

The returned object can only be used as a foreign function call parameter.It behaves similar topointer(obj), but the construction is a lot faster.

ctypes.cast(obj,type)

This function is similar to the cast operator in C. It returns a new instanceoftype which points to the same memory block asobj.type must be apointer type, andobj must be an object that can be interpreted as apointer.

ctypes.create_string_buffer(init_or_size,size=None)

This function creates a mutable character buffer. The returned object is actypes array ofc_char.

init_or_size must be an integer which specifies the size of the array, or abytes object which will be used to initialize the array items.

If a bytes object is specified as first argument, the buffer is made one itemlarger than its length so that the last element in the array is a NULtermination character. An integer can be passed as second argument which allowsspecifying the size of the array if the length of the bytes should not be used.

引發一個附帶引數initsize稽核事件ctypes.create_string_buffer

ctypes.create_unicode_buffer(init_or_size,size=None)

This function creates a mutable unicode character buffer. The returned object isa ctypes array ofc_wchar.

init_or_size must be an integer which specifies the size of the array, or astring which will be used to initialize the array items.

If a string is specified as first argument, the buffer is made one itemlarger than the length of the string so that the last element in the array is aNUL termination character. An integer can be passed as second argument whichallows specifying the size of the array if the length of the string should notbe used.

引發一個附帶引數initsize稽核事件ctypes.create_unicode_buffer

ctypes.DllCanUnloadNow()

This function is a hook which allows implementing in-processCOM servers with ctypes. It is called from the DllCanUnloadNow function thatthe _ctypes extension dll exports.

適用: Windows

ctypes.DllGetClassObject()

This function is a hook which allows implementing in-processCOM servers with ctypes. It is called from the DllGetClassObject functionthat the_ctypes extension dll exports.

適用: Windows

ctypes.util.find_library(name)

Try to find a library and return a pathname.name is the library namewithout any prefix likelib, suffix like.so,.dylib or versionnumber (this is the form used for the posix linker option-l). Ifno library can be found, returnsNone.

The exact functionality is system dependent.

ctypes.util.find_msvcrt()

Returns the filename of the VC runtime library used by Python,and by the extension modules. If the name of the library cannot bedetermined,None is returned.

If you need to free memory, for example, allocated by an extension modulewith a call to thefree(void*), it is important that you use thefunction in the same library that allocated the memory.

適用: Windows

ctypes.FormatError([code])

Returns a textual description of the error codecode. If noerror code is specified, the last error code is used by calling the Windowsapi function GetLastError.

適用: Windows

ctypes.GetLastError()

Returns the last error code set by Windows in the calling thread.This function calls the WindowsGetLastError() function directly,it does not return the ctypes-private copy of the error code.

適用: Windows

ctypes.get_errno()

Returns the current value of the ctypes-private copy of the systemerrno variable in the calling thread.

引發一個不附帶引數的稽核事件ctypes.get_errno

ctypes.get_last_error()

Returns the current value of the ctypes-private copy of the systemLastError variable in the calling thread.

適用: Windows

引發一個不附帶引數的稽核事件ctypes.get_last_error

ctypes.memmove(dst,src,count)

Same as the standard C memmove library function: copiescount bytes fromsrc todst.dst andsrc must be integers or ctypes instances that canbe converted to pointers.

ctypes.memset(dst,c,count)

Same as the standard C memset library function: fills the memory block ataddressdst withcount bytes of valuec.dst must be an integerspecifying an address, or a ctypes instance.

ctypes.POINTER(type,/)

Create and return a new ctypes pointer type. Pointer types are cached andreused internally, so calling this function repeatedly is cheap.type must be a ctypes type.

ctypes.pointer(obj,/)

Create a new pointer instance, pointing toobj.The returned object is of the typePOINTER(type(obj)).

Note: If you just want to pass a pointer to an object to a foreign functioncall, you should usebyref(obj) which is much faster.

ctypes.resize(obj,size)

This function resizes the internal memory buffer ofobj, which must be aninstance of a ctypes type. It is not possible to make the buffer smallerthan the native size of the objects type, as given bysizeof(type(obj)),but it is possible to enlarge the buffer.

ctypes.set_errno(value)

Set the current value of the ctypes-private copy of the systemerrnovariable in the calling thread tovalue and return the previous value.

引發一個附帶引數errno稽核事件ctypes.set_errno

ctypes.set_last_error(value)

Sets the current value of the ctypes-private copy of the systemLastError variable in the calling thread tovalue and return theprevious value.

適用: Windows

引發一個附帶引數error稽核事件ctypes.set_last_error

ctypes.sizeof(obj_or_type)

Returns the size in bytes of a ctypes type or instance memory buffer.Does the same as the Csizeof operator.

ctypes.string_at(ptr,size=-1)

Return the byte string atvoid *ptr.Ifsize is specified, it is used as size, otherwise the string is assumedto be zero-terminated.

引發一個附帶引數ptrsize稽核事件ctypes.string_at

ctypes.WinError(code=None,descr=None)

This function is probably the worst-named thing in ctypes. Itcreates an instance ofOSError. Ifcode is not specified,GetLastError is called to determine the error code. Ifdescr is notspecified,FormatError() is called to get a textual description of theerror.

適用: Windows

在 3.3 版的變更:An instance ofWindowsError used to be created, which is now analias ofOSError.

ctypes.wstring_at(ptr,size=-1)

Return the wide-character string atvoid *ptr.Ifsize is specified, it is used as the number ofcharacters of the string, otherwise the string is assumed to bezero-terminated.

引發一個附帶引數ptrsize稽核事件ctypes.wstring_at

Data types

classctypes._CData

This non-public class is the common base class of all ctypes data types.Among other things, all ctypes type instances contain a memory block thathold C compatible data; the address of the memory block is returned by theaddressof() helper function. Another instance variable is exposed as_objects; this contains other Python objects that need to be keptalive in case the memory block contains pointers.

Common methods of ctypes data types, these are all class methods (to beexact, they are methods of themetaclass):

from_buffer(source[,offset])

This method returns a ctypes instance that shares the buffer of thesource object. Thesource object must support the writeable bufferinterface. The optionaloffset parameter specifies an offset into thesource buffer in bytes; the default is zero. If the source buffer is notlarge enough aValueError is raised.

引發一個附帶引數pointersizeoffset稽核事件ctypes.cdata/buffer

from_buffer_copy(source[,offset])

This method creates a ctypes instance, copying the buffer from thesource object buffer which must be readable. The optionaloffsetparameter specifies an offset into the source buffer in bytes; the defaultis zero. If the source buffer is not large enough aValueError israised.

引發一個附帶引數pointersizeoffset稽核事件ctypes.cdata/buffer

from_address(address)

This method returns a ctypes type instance using the memory specified byaddress which must be an integer.

This method, and others that indirectly call this method, raises anauditing eventctypes.cdata with argumentaddress.

from_param(obj)

This method adaptsobj to a ctypes type. It is called with the actualobject used in a foreign function call when the type is present in theforeign function'sargtypes tuple;it must return an object that can be used as a function call parameter.

All ctypes data types have a default implementation of this classmethodthat normally returnsobj if that is an instance of the type. Sometypes accept other objects as well.

in_dll(library,name)

This method returns a ctypes type instance exported by a sharedlibrary.name is the name of the symbol that exports the data,libraryis the loaded shared library.

Common instance variables of ctypes data types:

_b_base_

Sometimes ctypes data instances do not own the memory block they contain,instead they share part of the memory block of a base object. The_b_base_ read-only member is the root ctypes object that owns thememory block.

_b_needsfree_

This read-only variable is true when the ctypes data instance hasallocated the memory block itself, false otherwise.

_objects

This member is eitherNone or a dictionary containing Python objectsthat need to be kept alive so that the memory block contents is keptvalid. This object is only exposed for debugging; never modify thecontents of this dictionary.

Fundamental data types

classctypes._SimpleCData

This non-public class is the base class of all fundamental ctypes datatypes. It is mentioned here because it contains the common attributes of thefundamental ctypes data types._SimpleCData is a subclass of_CData, so it inherits their methods and attributes. ctypes datatypes that are not and do not contain pointers can now be pickled.

Instances have a single attribute:

value

This attribute contains the actual value of the instance. For integer andpointer types, it is an integer, for character types, it is a singlecharacter bytes object or string, for character pointer types it is aPython bytes object or string.

When thevalue attribute is retrieved from a ctypes instance, usuallya new object is returned each time.ctypes doesnot implementoriginal object return, always a new object is constructed. The same istrue for all other ctypes object instances.

Fundamental data types, when returned as foreign function call results, or, forexample, by retrieving structure field members or array items, are transparentlyconverted to native Python types. In other words, if a foreign function has arestype ofc_char_p, you will always receive a Python bytesobject,not ac_char_p instance.

Subclasses of fundamental data types donot inherit this behavior. So, if aforeign functionsrestype is a subclass ofc_void_p, you willreceive an instance of this subclass from the function call. Of course, you canget the value of the pointer by accessing thevalue attribute.

These are the fundamental ctypes data types:

classctypes.c_byte

Represents the Csignedchar datatype, and interprets the value assmall integer. The constructor accepts an optional integer initializer; nooverflow checking is done.

classctypes.c_char

Represents the Cchar datatype, and interprets the value as a singlecharacter. The constructor accepts an optional string initializer, thelength of the string must be exactly one character.

classctypes.c_char_p

Represents the Cchar* datatype when it points to a zero-terminatedstring. For a general character pointer that may also point to binary data,POINTER(c_char) must be used. The constructor accepts an integeraddress, or a bytes object.

classctypes.c_double

Represents the Cdouble datatype. The constructor accepts anoptional float initializer.

classctypes.c_longdouble

Represents the Clongdouble datatype. The constructor accepts anoptional float initializer. On platforms wheresizeof(longdouble)==sizeof(double) it is an alias toc_double.

classctypes.c_float

Represents the Cfloat datatype. The constructor accepts anoptional float initializer.

classctypes.c_int

Represents the Csignedint datatype. The constructor accepts anoptional integer initializer; no overflow checking is done. On platformswheresizeof(int)==sizeof(long) it is an alias toc_long.

classctypes.c_int8

Represents the C 8-bitsignedint datatype. Usually an alias forc_byte.

classctypes.c_int16

Represents the C 16-bitsignedint datatype. Usually an alias forc_short.

classctypes.c_int32

Represents the C 32-bitsignedint datatype. Usually an alias forc_int.

classctypes.c_int64

Represents the C 64-bitsignedint datatype. Usually an alias forc_longlong.

classctypes.c_long

Represents the Csignedlong datatype. The constructor accepts anoptional integer initializer; no overflow checking is done.

classctypes.c_longlong

Represents the Csignedlonglong datatype. The constructor acceptsan optional integer initializer; no overflow checking is done.

classctypes.c_short

Represents the Csignedshort datatype. The constructor accepts anoptional integer initializer; no overflow checking is done.

classctypes.c_size_t

Represents the Csize_t datatype.

classctypes.c_ssize_t

Represents the Cssize_t datatype.

在 3.2 版被加入.

classctypes.c_time_t

Represents the Ctime_t datatype.

在 3.12 版被加入.

classctypes.c_ubyte

Represents the Cunsignedchar datatype, it interprets the value assmall integer. The constructor accepts an optional integer initializer; nooverflow checking is done.

classctypes.c_uint

Represents the Cunsignedint datatype. The constructor accepts anoptional integer initializer; no overflow checking is done. On platformswheresizeof(int)==sizeof(long) it is an alias forc_ulong.

classctypes.c_uint8

Represents the C 8-bitunsignedint datatype. Usually an alias forc_ubyte.

classctypes.c_uint16

Represents the C 16-bitunsignedint datatype. Usually an alias forc_ushort.

classctypes.c_uint32

Represents the C 32-bitunsignedint datatype. Usually an alias forc_uint.

classctypes.c_uint64

Represents the C 64-bitunsignedint datatype. Usually an alias forc_ulonglong.

classctypes.c_ulong

Represents the Cunsignedlong datatype. The constructor accepts anoptional integer initializer; no overflow checking is done.

classctypes.c_ulonglong

Represents the Cunsignedlonglong datatype. The constructoraccepts an optional integer initializer; no overflow checking is done.

classctypes.c_ushort

Represents the Cunsignedshort datatype. The constructor acceptsan optional integer initializer; no overflow checking is done.

classctypes.c_void_p

Represents the Cvoid* type. The value is represented as integer.The constructor accepts an optional integer initializer.

classctypes.c_wchar

Represents the Cwchar_t datatype, and interprets the value as asingle character unicode string. The constructor accepts an optional stringinitializer, the length of the string must be exactly one character.

classctypes.c_wchar_p

Represents the Cwchar_t* datatype, which must be a pointer to azero-terminated wide character string. The constructor accepts an integeraddress, or a string.

classctypes.c_bool

Represent the Cbool datatype (more accurately,_Bool fromC99). Its value can beTrue orFalse, and the constructor accepts any objectthat has a truth value.

classctypes.HRESULT

Represents aHRESULT value, which contains success orerror information for a function or method call.

適用: Windows

classctypes.py_object

Represents the CPyObject* datatype. Calling this without anargument creates aNULLPyObject* pointer.

Thectypes.wintypes module provides quite some other Windows specificdata types, for exampleHWND,WPARAM, orDWORD.Some useful structures likeMSG orRECT are also defined.

Structured data types

classctypes.Union(*args,**kw)

Abstract base class for unions in native byte order.

classctypes.BigEndianUnion(*args,**kw)

Abstract base class for unions inbig endian byte order.

在 3.11 版被加入.

classctypes.LittleEndianUnion(*args,**kw)

Abstract base class for unions inlittle endian byte order.

在 3.11 版被加入.

classctypes.BigEndianStructure(*args,**kw)

Abstract base class for structures inbig endian byte order.

classctypes.LittleEndianStructure(*args,**kw)

Abstract base class for structures inlittle endian byte order.

Structures and unions with non-native byte order cannot contain pointer typefields, or any other data types containing pointer type fields.

classctypes.Structure(*args,**kw)

Abstract base class for structures innative byte order.

Concrete structure and union types must be created by subclassing one of thesetypes, and at least define a_fields_ class variable.ctypes willcreatedescriptors which allow reading and writing the fields by directattribute accesses. These are the

_fields_

A sequence defining the structure fields. The items must be 2-tuples or3-tuples. The first item is the name of the field, the second itemspecifies the type of the field; it can be any ctypes data type.

For integer type fields likec_int, a third optional item can begiven. It must be a small positive integer defining the bit width of thefield.

Field names must be unique within one structure or union. This is notchecked, only one field can be accessed when names are repeated.

It is possible to define the_fields_ class variableafter theclass statement that defines the Structure subclass, this allows creatingdata types that directly or indirectly reference themselves:

classList(Structure):passList._fields_=[("pnext",POINTER(List)),...]

The_fields_ class variable must, however, be defined before thetype is first used (an instance is created,sizeof() is called on it,and so on). Later assignments to the_fields_ class variable willraise an AttributeError.

It is possible to define sub-subclasses of structure types, they inheritthe fields of the base class plus the_fields_ defined in thesub-subclass, if any.

_pack_

An optional small integer that allows overriding the alignment ofstructure fields in the instance._pack_ must already be definedwhen_fields_ is assigned, otherwise it will have no effect.Setting this attribute to 0 is the same as not setting it at all.

_align_

An optional small integer that allows overriding the alignment ofthe structure when being packed or unpacked to/from memory.Setting this attribute to 0 is the same as not setting it at all.

在 3.13 版被加入.

_anonymous_

An optional sequence that lists the names of unnamed (anonymous) fields._anonymous_ must be already defined when_fields_ isassigned, otherwise it will have no effect.

The fields listed in this variable must be structure or union type fields.ctypes will create descriptors in the structure type that allowsaccessing the nested fields directly, without the need to create thestructure or union field.

Here is an example type (Windows):

class_U(Union):_fields_=[("lptdesc",POINTER(TYPEDESC)),("lpadesc",POINTER(ARRAYDESC)),("hreftype",HREFTYPE)]classTYPEDESC(Structure):_anonymous_=("u",)_fields_=[("u",_U),("vt",VARTYPE)]

TheTYPEDESC structure describes a COM data type, thevt fieldspecifies which one of the union fields is valid. Since theu fieldis defined as anonymous field, it is now possible to access the membersdirectly off the TYPEDESC instance.td.lptdesc andtd.u.lptdescare equivalent, but the former is faster since it does not need to createa temporary union instance:

td=TYPEDESC()td.vt=VT_PTRtd.lptdesc=POINTER(some_type)td.u.lptdesc=POINTER(some_type)

It is possible to define sub-subclasses of structures, they inherit thefields of the base class. If the subclass definition has a separate_fields_ variable, the fields specified in this are appended to thefields of the base class.

Structure and union constructors accept both positional and keywordarguments. Positional arguments are used to initialize member fields in thesame order as they are appear in_fields_. Keyword arguments in theconstructor are interpreted as attribute assignments, so they will initialize_fields_ with the same name, or create new attributes for names notpresent in_fields_.

Arrays and pointers

classctypes.Array(*args)

Abstract base class for arrays.

The recommended way to create concrete array types is by multiplying anyctypes data type with a non-negative integer. Alternatively, you can subclassthis type and define_length_ and_type_ class variables.Array elements can be read and written using standardsubscript and slice accesses; for slice reads, the resulting object isnot itself anArray.

_length_

A positive integer specifying the number of elements in the array.Out-of-range subscripts result in anIndexError. Will bereturned bylen().

_type_

Specifies the type of each element in the array.

Array subclass constructors accept positional arguments, used toinitialize the elements in order.

ctypes.ARRAY(type,length)

Create an array.Equivalent totype*length, wheretype is actypes data type andlength an integer.

This function issoft deprecated in favor of multiplication.There are no plans to remove it.

classctypes._Pointer

Private, abstract base class for pointers.

Concrete pointer types are created by callingPOINTER() with thetype that will be pointed to; this is done automatically bypointer().

If a pointer points to an array, its elements can be read andwritten using standard subscript and slice accesses. Pointer objectshave no size, solen() will raiseTypeError. Negativesubscripts will read from the memorybefore the pointer (as in C), andout-of-range subscripts will probably crash with an access violation (ifyou're lucky).

_type_

Specifies the type pointed to.

contents

Returns the object to which to pointer points. Assigning to thisattribute changes the pointer to point to the assigned object.