NoteThe code samples in this tutorial use doctest to make sure thatthey actually work. Since some code samples behave differently under Linux,Windows, or macOS, they contain doctest directives in comments.
You load libraries by accessing them as attributes of these objects. cdllloads libraries which export functions using the standard cdecl callingconvention, while windll libraries call functions using the stdcallcalling convention. oledll also uses the stdcall calling convention, andassumes the functions return a Windows HRESULT error code. The errorcode is used to automatically raise an OSError exception when thefunction call fails.
Accessing the standard C library through cdll.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 the msvcrt module.
On Linux, it is required to specify the filename including 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:
Note that win32 system dlls like kernel32 and user32 often export ANSIas well as UNICODE versions of a function. The UNICODE version is exported witha W appended to the name, while the ANSI version is exported with an Aappended to the name. The win32 GetModuleHandle function, which returns amodule handle for a given module name, has the following C prototype, and amacro is used to expose one of them as GetModuleHandle depending on whetherUNICODE is defined or not:
windll does not try to select one of them by magic, you must access theversion you need by specifying GetModuleHandleA or GetModuleHandleWexplicitly, and then call it with bytes or string objects respectively.
There are, however, enough ways to crash Python with ctypes, so youshould be careful anyway. The faulthandler 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 C NULL 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 platforms default Cint type, their value is masked to fit into the C type.
Assigning a new value to instances of the pointer types c_char_p,c_wchar_p, and c_void_p changes the memory location theypoint to, not the contents of the memory block (of course not, because Pythonbytes objects are immutable):
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 the rawproperty; if you want to access it as NUL terminated string, use the valueproperty:
As has been mentioned before, all Python types except integers, strings, andbytes objects have to be wrapped in their corresponding ctypes type, sothat they can be converted to the required C data type:
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.
You can also customize ctypes 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, a ctypes instance, or anobject with an _as_parameter_ attribute:
argtypes must be a sequence of C data types (the printf() 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):
If you have defined your own classes which you pass to function calls, you haveto implement a from_param() class method for them to be able to use themin the argtypes sequence. The from_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, a ctypes instance, or an object with an_as_parameter_ attribute.
You can also use a callable Python object (a function or a class for example) asthe restype attribute, if the foreign function returns an integer. Thecallable will be called with the integer 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:
WinError is a function which will call Windows FormatMessage() api toget the string representation of an error code, and returns an exception.WinError takes an optional error code parameter, if no one is used, it callsGetLastError() to retrieve it.
Sometimes a C api function expects a pointer 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 as passing parameters by reference.
Structures and unions must derive from the Structure and Unionbase classes which are defined in the ctypes module. Each subclass mustdefine a _fields_ attribute. _fields_ must be a list of2-tuples, containing a field name and a field type.
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 #pragma pack(n) also does in MSVC.
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, and LittleEndianUnion base classes. Theseclasses cannot contain pointer fields.
Behind the scenes, the pointer() function does more than simply createpointer instances, it has to create pointer types first. This is done with thePOINTER() function, which accepts any ctypes type, and returns anew type:
Usually, ctypes does strict type checking. This means, if you havePOINTER(c_int) in the argtypes 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, for POINTER(c_int), ctypes accepts an array of c_int:
In addition, if a function argument is explicitly declared to be a pointer type(such as POINTER(c_int)) in argtypes, an object of the pointedtype (c_int in this case) can be passed to the function. ctypes will applythe required byref() conversion in this case automatically.
Sometimes you have instances of incompatible types. In C, you can cast one typeinto another type. ctypes provides a cast() function which can beused in the same way. The Bar structure defined above acceptsPOINTER(c_int) pointers or c_int arrays for its values field,but not instances of other types:
The cast() 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:
The CFUNCTYPE() factory function creates types for callback functionsusing the cdecl calling convention. On Windows, the WINFUNCTYPE()factory function creates types for callback functions using the stdcallcalling convention.
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.
Some shared libraries not only export functions, they also export variables. Anexample in the Python library itself is the Py_Version, Pythonruntime version number encoded in a single constant integer.
This pointer is initialized to point to an array of _frozenrecords, terminated by one whose members are all NULL 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.
The fact that standard Python has a frozen module and a frozen package(indicated by the negative size member) is not well known, it is only usedfor testing. Try it out with import __hello__ for example.
Why is it printing False? ctypes instances are objects containing a memoryblock plus some descriptors accessing the contents of the memory.Storing a Python object in the memory block does not store the object itself,instead the contents of the object is stored. Accessing the contents againconstructs a new Python object each time!
The resize() 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:
The purpose of the find_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.
3a8082e126