From 56dab85022026ccfbc73bf1657ca71c5649792a6 Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Tue, 6 Jun 2006 15:34:18 +0000 Subject: [PATCH] Specify argtypes for all test functions. Maybe that helps on strange ;-) architectures --- Doc/lib/lib.tex | 1 - Doc/lib/libctypes.tex | 1023 ++++++++++++++++++++++++++++---- Lib/ctypes/test/test_cfuncs.py | 8 + 3 files changed, 924 insertions(+), 108 deletions(-) diff --git a/Doc/lib/lib.tex b/Doc/lib/lib.tex index 0691179acb5..5f357e37e2c 100644 --- a/Doc/lib/lib.tex +++ b/Doc/lib/lib.tex @@ -245,7 +245,6 @@ and how to embed it in other applications. \input{libplatform} \input{liberrno} \input{libctypes} -\input{libctypesref} \input{libsomeos} % Optional Operating System Services \input{libselect} diff --git a/Doc/lib/libctypes.tex b/Doc/lib/libctypes.tex index dc37749e3e0..2533bbad966 100755 --- a/Doc/lib/libctypes.tex +++ b/Doc/lib/libctypes.tex @@ -1,4 +1,4 @@ -\newlength{\locallinewidth} +\ifx\locallinewidth\undefined\newlength{\locallinewidth}\fi \setlength{\locallinewidth}{\linewidth} \section{\module{ctypes} --- A foreign function library for Python.} \declaremodule{standard}{ctypes} @@ -70,6 +70,12 @@ calling the constructor: XXX Add section for Mac OS X. +\subsubsection{Finding shared libraries\label{ctypes-finding-shared-libraries}} + +XXX Add description of ctypes.util.find{\_}library (once I really +understand it enough to describe it). + + \subsubsection{Accessing functions from loaded dlls\label{ctypes-accessing-functions-from-loaded-dlls}} Functions are accessed as attributes of dll objects: @@ -186,158 +192,172 @@ Before we move on calling functions with other parameter types, we have to learn more about \code{ctypes} data types. -\subsubsection{Simple data types\label{ctypes-simple-data-types}} +\subsubsection{Fundamental data types\label{ctypes-fundamental-data-types}} \code{ctypes} defines a number of primitive C compatible data types : \begin{quote} - -\begin{longtable}[c]{|p{0.19\locallinewidth}|p{0.28\locallinewidth}|p{0.14\locallinewidth}|} -\hline -\textbf{ +\begin{tableiii}{l|l|l}{textrm} +{ ctypes type -} & \textbf{ +} +{ C type -} & \textbf{ +} +{ Python type -} \\ -\hline -\endhead - +} +\lineiii{ \class{c{\_}char} - & +} +{ \code{char} - & +} +{ character - \\ -\hline - +} +\lineiii{ \class{c{\_}byte} - & +} +{ \code{char} - & +} +{ integer - \\ -\hline - +} +\lineiii{ \class{c{\_}ubyte} - & +} +{ \code{unsigned char} - & +} +{ integer - \\ -\hline - +} +\lineiii{ \class{c{\_}short} - & +} +{ \code{short} - & +} +{ integer - \\ -\hline - +} +\lineiii{ \class{c{\_}ushort} - & +} +{ \code{unsigned short} - & +} +{ integer - \\ -\hline - +} +\lineiii{ \class{c{\_}int} - & +} +{ \code{int} - & +} +{ integer - \\ -\hline - +} +\lineiii{ \class{c{\_}uint} - & +} +{ \code{unsigned int} - & +} +{ integer - \\ -\hline - +} +\lineiii{ \class{c{\_}long} - & +} +{ \code{long} - & +} +{ integer - \\ -\hline - +} +\lineiii{ \class{c{\_}ulong} - & +} +{ \code{unsigned long} - & +} +{ long - \\ -\hline - +} +\lineiii{ \class{c{\_}longlong} - & +} +{ \code{{\_}{\_}int64} or \code{long long} - & +} +{ long - \\ -\hline - +} +\lineiii{ \class{c{\_}ulonglong} - & +} +{ \code{unsigned {\_}{\_}int64} or \code{unsigned long long} - & +} +{ long - \\ -\hline - +} +\lineiii{ \class{c{\_}float} - & +} +{ \code{float} - & +} +{ float - \\ -\hline - +} +\lineiii{ \class{c{\_}double} - & +} +{ \code{double} - & +} +{ float - \\ -\hline - +} +\lineiii{ \class{c{\_}char{\_}p} - & +} +{ \code{char *} (NUL terminated) - & +} +{ string or \code{None} - \\ -\hline - +} +\lineiii{ \class{c{\_}wchar{\_}p} - & +} +{ \code{wchar{\_}t *} (NUL terminated) - & +} +{ unicode or \code{None} - \\ -\hline - +} +\lineiii{ \class{c{\_}void{\_}p} - & +} +{ \code{void *} - & +} +{ integer or \code{None} - \\ -\hline -\end{longtable} +} +\end{tableiii} \end{quote} All these types can be created by calling them with an optional @@ -380,6 +400,7 @@ c_char_p('Hello, World') c_char_p('Hi, there') >>> print s # first string is unchanged Hello, World +>>> \end{verbatim} You should be careful, however, not to pass them to functions @@ -575,7 +596,7 @@ for error return values and automatically raise an exception: >>> GetModuleHandle.restype = ValidHandle # doctest: +WINDOWS >>> GetModuleHandle(None) # doctest: +WINDOWS 486539264 ->>> GetModuleHandle("something silly") # doctest: +WINDOWS +IGNORE_EXCEPTION_DETAIL +>>> GetModuleHandle("something silly") # doctest: +WINDOWS Traceback (most recent call last): File "", line 1, in ? File "", line 3, in ValidHandle @@ -744,6 +765,7 @@ containing 4 POINTs among other stuff: >>> >>> print len(MyStruct().point_array) 4 +>>> \end{verbatim} Instances are created in the usual way, by calling the class: @@ -772,6 +794,10 @@ Initializers of the correct type can also be specified: \subsubsection{Pointers\label{ctypes-pointers}} +XXX Rewrite this section. Normally one only uses indexing, not the .contents +attribute! +List some recipes with pointers. bool(ptr), POINTER(tp)(), ...? + Pointer instances are created by calling the \code{pointer} function on a \code{ctypes} type: \begin{verbatim} @@ -781,16 +807,25 @@ Pointer instances are created by calling the \code{pointer} function on a >>> \end{verbatim} -XXX XXX Not correct: use indexing, not the contents atribute - Pointer instances have a \code{contents} attribute which returns the -ctypes' type pointed to, the \code{c{\_}int(42)} in the above case: +object to which the pointer points, the \code{i} object above: \begin{verbatim} >>> pi.contents c_long(42) >>> \end{verbatim} +Note that \code{ctypes} does not have OOR (original object return), it +constructs a new, equivalent object each time you retrieve an +attribute: +\begin{verbatim} +>>> pi.contents is i +False +>>> pi.contents is pi.contents +False +>>> +\end{verbatim} + Assigning another \class{c{\_}int} instance to the pointer's contents attribute would cause the pointer to point to the memory location where this is stored: @@ -808,23 +843,21 @@ Pointer instances can also be indexed with integers: >>> \end{verbatim} -XXX What is this??? Assigning to an integer index changes the pointed to value: \begin{verbatim} ->>> i2 = pi[0] ->>> i2 -99 +>>> print i +c_long(99) >>> pi[0] = 22 ->>> i2 -99 +>>> print i +c_long(22) >>> \end{verbatim} It is also possible to use indexes different from 0, but you must know -what you're doing when you use this: You access or change arbitrary -memory locations when you do this. Generally you only use this feature -if you receive a pointer from a C function, and you \emph{know} that the -pointer actually points to an array instead of a single item. +what you'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 you \emph{know} that the pointer actually +points to an array instead of a single item. \subsubsection{Pointer classes/types\label{ctypes-pointer-classestypes}} @@ -837,7 +870,7 @@ This is done with the \code{POINTER} function, which accepts any >>> PI = POINTER(c_int) >>> PI ->>> PI(42) # doctest: +IGNORE_EXCEPTION_DETAIL +>>> PI(42) Traceback (most recent call last): File "", line 1, in ? TypeError: expected c_long instead of int @@ -847,6 +880,82 @@ TypeError: expected c_long instead of int \end{verbatim} +\subsubsection{Type conversions\label{ctypes-type-conversions}} + +Usually, ctypes does strict type checking. This means, if you have +\code{POINTER(c{\_}int)} in the \member{argtypes} list of a function or in the +\member{{\_}fields{\_}} of a structure definition, only instances of exactly the +same type are accepted. There are some exceptions to this rule, where +ctypes accepts other objects. For example, you can pass compatible +array instances instead of pointer types. So, for \code{POINTER(c{\_}int)}, +ctypes accepts an array of c{\_}int values: +\begin{verbatim} +>>> class Bar(Structure): +... _fields_ = [("count", c_int), ("values", POINTER(c_int))] +... +>>> bar = Bar() +>>> print bar._objects +None +>>> bar.values = (c_int * 3)(1, 2, 3) +>>> print bar._objects +{'1': ({}, )} +>>> bar.count = 3 +>>> for i in range(bar.count): +... print bar.values[i] +... +1 +2 +3 +>>> +\end{verbatim} + +To set a POINTER type field to \code{NULL}, you can assign \code{None}: +\begin{verbatim} +>>> bar.values = None +>>> +\end{verbatim} + +XXX list other conversions... + +Sometimes you have instances of incompatible types. In \code{C}, you can +cast one type into another type. \code{ctypes} provides a \code{cast} +function which can be used in the same way. The Bar structure defined +above accepts \code{POINTER(c{\_}int)} pointers or \class{c{\_}int} arrays for its +\code{values} field, but not instances of other types: +\begin{verbatim} +>>> bar.values = (c_byte * 4)() +Traceback (most recent call last): + File "", line 1, in ? +TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance +>>> +\end{verbatim} + +For these cases, the \code{cast} function is handy. + +The \code{cast} function can be used to cast a ctypes instance into a +pointer to a different ctypes data type. \code{cast} takes two +parameters, a ctypes object that is or can be converted to a pointer +of some kind, and a ctypes pointer type. It returns an instance of +the second argument, which references the same memory block as the +first argument: +\begin{verbatim} +>>> a = (c_byte * 4)() +>>> cast(a, POINTER(c_int)) + +>>> +\end{verbatim} + +So, \code{cast} can be used to assign to the \code{values} field of \code{Bar} +the structure: +\begin{verbatim} +>>> bar = Bar() +>>> bar.values = cast((c_byte * 4)(), POINTER(c_int)) +>>> print bar.values[0] +0 +>>> +\end{verbatim} + + \subsubsection{Incomplete Types\label{ctypes-incomplete-types}} \emph{Incomplete Types} are structures, unions or arrays whose members are @@ -1175,6 +1284,7 @@ Consider the following example: >>> 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 +>>> \end{verbatim} Hm. We certainly expected the last statement to print \code{3 4 1 2}. @@ -1184,6 +1294,7 @@ line above: >>> temp0, temp1 = rc.b, rc.a >>> rc.a = temp0 >>> rc.b = temp1 +>>> \end{verbatim} Note that \code{temp0} and \code{temp1} are objects still using the internal @@ -1214,6 +1325,80 @@ the object itself, instead the \code{contents} of the object is stored. Accessing the contents again constructs a new Python each time! +\subsubsection{Variable-sized data types\label{ctypes-variable-sized-data-types}} + +\code{ctypes} provides some support for variable-sized arrays and +structures (this was added in version 0.9.9.7). + +The \code{resize} function can be used to resize the memory buffer of an +existing ctypes object. The function takes the object as first +argument, and the requested size in bytes as the second argument. The +memory block cannot be made smaller than the natural memory block +specified by the objects type, a \code{ValueError} is raised if this is +tried: +\begin{verbatim} +>>> 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 +>>> +\end{verbatim} + +This is nice and fine, but how would one access the additional +elements contained in this array? Since the type still only knows +about 4 elements, we get errors accessing other elements: +\begin{verbatim} +>>> short_array[:] +[0, 0, 0, 0] +>>> short_array[7] +Traceback (most recent call last): + ... +IndexError: invalid index +>>> +\end{verbatim} + +The solution is to use 1-element arrays; as a special case ctypes does +no bounds checking on them: +\begin{verbatim} +>>> short_array = (c_short * 1)() +>>> print sizeof(short_array) +2 +>>> resize(short_array, 32) +>>> sizeof(short_array) +32 +>>> sizeof(type(short_array)) +2 +>>> short_array[0:8] +[0, 0, 0, 0, 0, 0, 0, 0] +>>> short_array[7] = 42 +>>> short_array[0:8] +[0, 0, 0, 0, 0, 0, 0, 42] +>>> +\end{verbatim} + +Using 1-element arrays as variable sized fields in structures works as +well, but they should be used as the last field in the structure +definition. This example shows a definition from the Windows header +files: +\begin{verbatim} +class SP_DEVICE_INTERFACE_DETAIL_DATA(Structure): + _fields_ = [("cbSize", c_int), + ("DevicePath", c_char * 1)] +\end{verbatim} + +Another way to use variable-sized data types with \code{ctypes} is to use +the dynamic nature of Python, and (re-)define the data type after the +required size is already known, on a case by case basis. + + \subsubsection{Bugs, ToDo and non-implemented things\label{ctypes-bugs-todo-non-implemented-things}} Enumeration types are not implemented. You can do it easily yourself, @@ -1224,3 +1409,627 @@ using \class{c{\_}int} as the base class. % compile-command: "make.bat" % End: + +\subsection{ctypes reference\label{ctypes-ctypes-reference}} + + +\subsubsection{loading shared libraries\label{ctypes-loading-shared-libraries}} + +\begin{classdesc}{LibraryLoader}{dlltype} +Class which loads shared libraries. +\end{classdesc} + +\begin{methoddesc}{LoadLibrary}{name, mode=RTLD_LOCAL, handle=None} +Load a shared library. +\end{methoddesc} + +\begin{classdesc}{CDLL}{name, mode=RTLD_LOCAL, handle=None} +XXX +\end{classdesc} + +\begin{datadescni}{cdll} +XXX +\end{datadescni} + +\begin{funcdesc}{OleDLL}{name, mode=RTLD_LOCAL, handle=None} +XXX +\end{funcdesc} + +\begin{datadescni}{oledll} +XXX +\end{datadescni} + +\begin{classdesc*}{py_object} +XXX +\end{classdesc*} + +\begin{funcdesc}{PyDLL}{name, mode=RTLD_LOCAL, handle=None} +XXX +\end{funcdesc} + +\begin{datadescni}{pydll} +XXX +\end{datadescni} + +\begin{datadescni}{RTLD_GLOBAL} +XXX +\end{datadescni} + +\begin{datadescni}{RTLD_LOCAL} +XXX +\end{datadescni} + +\begin{funcdesc}{WinDLL}{name, mode=RTLD_LOCAL, handle=None} +XXX +\end{funcdesc} + +\begin{datadescni}{windll} +XXX +\end{datadescni} + +\begin{datadescni}{pythonapi()} +XXX +\end{datadescni} + + +\subsubsection{foreign functions\label{ctypes-foreign-functions}} + +The ultimate goal of \code{ctypes} is to call functions in shared +libraries, aka as foreign functions. Foreign function instances can +be created by accessing them as attributes of loaded shared libraries, +or by instantiating a \emph{function prototype}. + +Function prototypes are created by factory functions. + +They are created by calling one of the following factory functions: + +\begin{funcdesc}{CFUNCTYPE}{restype, *argtypes} +This is a factory function that returns a function prototype. The +function prototype describes a function that has a result type of +\member{restype}, and accepts arguments as specified by +\member{argtypes}. The function prototype can be used to construct +several kinds of functions, depending on how the prototype is +called. + +The prototypes returned by \function{CFUNCTYPE} or \code{PYFUNCTYPE} create +functions that use the standard C calling convention, prototypes +returned from \function{WINFUNCTYPE} (on Windows) use the \code{{\_}{\_}stdcall} +calling convention. + +Functions created by calling the \function{CFUNCTYPE} and \function{WINFUNCTYPE} +prototypes release the Python GIL before entering the foreign +function, and acquire it back after leaving the function code. +\end{funcdesc} + +\begin{funcdesc}{WINFUNCTYPE}{restype, *argtypes} +TBD +\end{funcdesc} + +\begin{funcdesc}{PYFUNCTYPE}{restype, *argtypes} +TBD +\end{funcdesc} + +\begin{excdesc}{ArgumentError()} +This exception is raised when a foreign function call cannot +convert one of the passed arguments. +\end{excdesc} + + +\subsubsection{helper functions\label{ctypes-helper-functions}} + +\begin{funcdesc}{addressof}{obj} +Returns the address of the memory buffer as integer. \code{obj} must +be an instance of a ctypes type. +\end{funcdesc} + +\begin{funcdesc}{alignment}{obj_or_type} +Returns the alignment requirements of a ctypes type. +\code{obj{\_}or{\_}type} must be a ctypes type or instance. +\end{funcdesc} + +\begin{funcdesc}{byref}{obj} +Returns a light-weight pointer to \code{obj}, which must be an +instance of a ctypes type. The returned object can only be used as +a foreign function call parameter. It behaves similar to +\code{pointer(obj)}, but the construction is a lot faster. +\end{funcdesc} + +\begin{funcdesc}{cast}{obj, type} +This function is similar to the cast operator in C. It returns a +new instance of \code{type} which points to the same memory block as +\code{obj}. \code{type} must be a pointer type, and \code{obj} must be an +object that can be interpreted as a pointer. +\end{funcdesc} + +\begin{funcdesc}{create_string_buffer}{init_or_size\optional{, size}} +This function creates a mutable character buffer. The returned +object is a ctypes array of \class{c{\_}char}. + +\code{init{\_}or{\_}size} must be an integer which specifies the size of +the array, or a string which will be used to initialize the array +items. + +If a string is specified as first argument, the buffer is made one +item larger than the length of the string so that the last element +in the array is a NUL termination character. An integer can be +passed as second argument which allows to specify the size of the +array if the length of the string should not be used. + +If the first parameter is a unicode string, it is converted into +an 8-bit string according to ctypes conversion rules. +\end{funcdesc} + +\begin{funcdesc}{create_unicode_buffer}{init_or_size\optional{, size}} +This function creates a mutable unicode character buffer. The +returned object is a ctypes array of \class{c{\_}wchar}. + +\code{init{\_}or{\_}size} must be an integer which specifies the size of +the array, or a unicode string which will be used to initialize +the array items. + +If a unicode string is specified as first argument, the buffer is +made one item larger than the length of the string so that the +last element in the array is a NUL termination character. An +integer can be passed as second argument which allows to specify +the size of the array if the length of the string should not be +used. + +If the first parameter is a 8-bit string, it is converted into an +unicode string according to ctypes conversion rules. +\end{funcdesc} + +\begin{funcdesc}{DllCanUnloadNow}{} +Windows only: This function is a hook which allows to implement +inprocess COM servers with ctypes. It is called from the +DllCanUnloadNow function that the {\_}ctypes extension dll exports. +\end{funcdesc} + +\begin{funcdesc}{DllGetClassObject}{} +Windows only: This function is a hook which allows to implement +inprocess COM servers with ctypes. It is called from the +DllGetClassObject function that the \code{{\_}ctypes} extension dll exports. +\end{funcdesc} + +\begin{funcdesc}{FormatError}{\optional{code}} +Windows only: Returns a textual description of the error code. If +no error code is specified, the last error code is used by calling +the Windows api function GetLastError. +\end{funcdesc} + +\begin{funcdesc}{GetLastError}{} +Windows only: Returns the last error code set by Windows in the +calling thread. +\end{funcdesc} + +\begin{funcdesc}{memmove}{dst, src, count} +Same as the standard C memmove library function: copies \var{count} +bytes from \code{src} to \var{dst}. \var{dst} and \code{src} must be +integers or ctypes instances that can be converted to pointers. +\end{funcdesc} + +\begin{funcdesc}{memset}{dst, c, count} +Same as the standard C memset library function: fills the memory +block at address \var{dst} with \var{count} bytes of value +\var{c}. \var{dst} must be an integer specifying an address, or a +ctypes instance. +\end{funcdesc} + +\begin{funcdesc}{POINTER}{type} +This factory function creates and returns a new ctypes pointer +type. Pointer types are cached an reused internally, so calling +this function repeatedly is cheap. type must be a ctypes type. +\end{funcdesc} + +\begin{funcdesc}{pointer}{obj} +This function creates a new pointer instance, pointing to +\code{obj}. The returned object is of the type POINTER(type(obj)). + +Note: If you just want to pass a pointer to an object to a foreign +function call, you should use \code{byref(obj)} which is much faster. +\end{funcdesc} + +\begin{funcdesc}{resize}{obj, size} +This function resizes the internal memory buffer of obj, which +must be an instance of a ctypes type. It is not possible to make +the buffer smaller than the native size of the objects type, as +given by sizeof(type(obj)), but it is possible to enlarge the +buffer. +\end{funcdesc} + +\begin{funcdesc}{set_conversion_mode}{encoding, errors} +This function sets the rules that ctypes objects use when +converting between 8-bit strings and unicode strings. encoding +must be a string specifying an encoding, like \code{'utf-8'} or +\code{'mbcs'}, errors must be a string specifying the error handling +on encoding/decoding errors. Examples of possible values are +\code{"strict"}, \code{"replace"}, or \code{"ignore"}. + +set{\_}conversion{\_}mode returns a 2-tuple containing the previous +conversion rules. On windows, the initial conversion rules are +\code{('mbcs', 'ignore')}, on other systems \code{('ascii', 'strict')}. +\end{funcdesc} + +\begin{funcdesc}{sizeof}{obj_or_type} +Returns the size in bytes of a ctypes type or instance memory +buffer. Does the same as the C \code{sizeof()} function. +\end{funcdesc} + +\begin{funcdesc}{string_at}{address\optional{, size}} +This function returns the string starting at memory address +address. If size is specified, it is used as size, otherwise the +string is assumed to be zero-terminated. +\end{funcdesc} + +\begin{funcdesc}{WinError}{code=None, descr=None} +Windows only: this function is probably the worst-named thing in +ctypes. It creates an instance of WindowsError. If \var{code} is not +specified, \code{GetLastError} is called to determine the error +code. If \code{descr} is not spcified, \function{FormatError} is called to +get a textual description of the error. +\end{funcdesc} + +\begin{funcdesc}{wstring_at}{address} +This function returns the wide character string starting at memory +address \code{address} as unicode string. If \code{size} is specified, +it is used as the number of characters of the string, otherwise +the string is assumed to be zero-terminated. +\end{funcdesc} + + +\subsubsection{Data types\label{ctypes-data-types}} + +\begin{classdesc*}{_CData} +This non-public class is the base class of all ctypes data types. +Among other things, all ctypes type instances contain a memory +block that hold C compatible data; the address of the memory block +is returned by the \code{addressof()} helper function. Another +instance variable is exposed as \member{{\_}objects}; this contains other +Python objects that need to be kept alive in case the memory block +contains pointers. +\end{classdesc*} + +Common methods of ctypes data types, these are all class methods (to +be exact, they are methods of the metaclass): + +\begin{methoddesc}{from_address}{address} +This method returns a ctypes type instance using the memory +specified by address. +\end{methoddesc} + +\begin{methoddesc}{from_param}{obj} +This method adapts obj to a ctypes type. +\end{methoddesc} + +\begin{methoddesc}{in_dll}{name, library} +This method returns a ctypes type instance exported by a shared +library. \var{name} is the name of the symbol that exports the data, +\code{library} is the loaded shared library. +\end{methoddesc} + +Common instance variables of ctypes data types: + +\begin{memberdesc}{_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 \member{{\_}b{\_}base{\_}} readonly member is the root ctypes +object that owns the memory block. +\end{memberdesc} + +\begin{memberdesc}{_b_needsfree_} +This readonly variable is true when the ctypes data instance has +allocated the memory block itself, false otherwise. +\end{memberdesc} + +\begin{memberdesc}{_objects} +This member is either \code{None} or a dictionary containing Python +objects that need to be kept alive so that the memory block +contents is kept valid. This object is only exposed for +debugging; never modify the contents of this dictionary. +\end{memberdesc} + + +\subsubsection{Fundamental data types\label{ctypes-fundamental-data-types}} + +\begin{classdesc*}{_SimpleCData} +This non-public class is the base class of all fundamental ctypes +data types. It is mentioned here because it contains the common +attributes of the fundamental ctypes data types. \code{{\_}SimpleCData} +is a subclass of \code{{\_}CData}, so it inherits the methods and +attributes of that. +\end{classdesc*} + +Instances have a single attribute: + +\begin{memberdesc}{value} +This attribute contains the actual value of the instance. For +integer and pointer types, it is an integer, for character types, +it is a single character string, for character pointer types it +is a Python string or unicode string. + +When the \code{value} attribute is retrieved from a ctypes instance, +usually a new object is returned each time. \code{ctypes} does \emph{not} +implement original object return, always a new object is +constructed. The same is true for all other ctypes object +instances. +\end{memberdesc} + +Fundamental data types, whether returned as result of foreign function +calls, or, for example, by retrieving structure field members, are +transparently converted to native Python types. In other words, if a +foreign function has a \member{restype} of \class{c{\_}char{\_}p}, you will always +receive a Python string, \emph{not} a \class{c{\_}char{\_}p} instance. + +Subclasses of fundamental data types do \emph{not} inherit this behaviour. +So, if a foreign functions \member{restype} is a subclass of \class{c{\_}void{\_}p}, +you will receive an instance of this subclass from the function call. +Of course, you can get the value of the pointer by accessing the +\code{value} attribute. + +These are the fundamental ctypes data types: + +\begin{classdesc*}{c_byte} +Represents the C signed char datatype, and interprets the value as +small integer. The constructor accepts an optional integer +initializer; no overflow checking is done. +\end{classdesc*} + +\begin{classdesc*}{c_char} +Represents the C char datatype, and interprets the value as a single +character. The constructor accepts an optional string initializer, +the length of the string must be exactly one character. +\end{classdesc*} + +\begin{classdesc*}{c_char_p} +Represents the C char * datatype, which must be a pointer to a +zero-terminated string. The constructor accepts an integer +address, or a string. +\end{classdesc*} + +\begin{classdesc*}{c_double} +Represents the C double datatype. The constructor accepts an +optional float initializer. +\end{classdesc*} + +\begin{classdesc*}{c_float} +Represents the C double datatype. The constructor accepts an +optional float initializer. +\end{classdesc*} + +\begin{classdesc*}{c_int} +Represents the C signed int datatype. The constructor accepts an +optional integer initializer; no overflow checking is done. On +platforms where \code{sizeof(int) == sizeof(long)} it is an alias to +\class{c{\_}long}. +\end{classdesc*} + +\begin{classdesc*}{c_int8} +Represents the C 8-bit \code{signed int} datatype. Usually an alias for +\class{c{\_}byte}. +\end{classdesc*} + +\begin{classdesc*}{c_int16} +Represents the C 16-bit signed int datatype. Usually an alias for +\class{c{\_}short}. +\end{classdesc*} + +\begin{classdesc*}{c_int32} +Represents the C 32-bit signed int datatype. Usually an alias for +\class{c{\_}int}. +\end{classdesc*} + +\begin{classdesc*}{c_int64} +Represents the C 64-bit \code{signed int} datatype. Usually an alias +for \class{c{\_}longlong}. +\end{classdesc*} + +\begin{classdesc*}{c_long} +Represents the C \code{signed long} datatype. The constructor accepts an +optional integer initializer; no overflow checking is done. +\end{classdesc*} + +\begin{classdesc*}{c_longlong} +Represents the C \code{signed long long} datatype. The constructor accepts +an optional integer initializer; no overflow checking is done. +\end{classdesc*} + +\begin{classdesc*}{c_short} +Represents the C \code{signed short} datatype. The constructor accepts an +optional integer initializer; no overflow checking is done. +\end{classdesc*} + +\begin{classdesc*}{c_size_t} +Represents the C \code{size{\_}t} datatype. +\end{classdesc*} + +\begin{classdesc*}{c_ubyte} +Represents the C \code{unsigned char} datatype, it interprets the +value as small integer. The constructor accepts an optional +integer initializer; no overflow checking is done. +\end{classdesc*} + +\begin{classdesc*}{c_uint} +Represents the C \code{unsigned int} datatype. The constructor accepts an +optional integer initializer; no overflow checking is done. On +platforms where \code{sizeof(int) == sizeof(long)} it is an alias for +\class{c{\_}ulong}. +\end{classdesc*} + +\begin{classdesc*}{c_uint8} +Represents the C 8-bit unsigned int datatype. Usually an alias for +\class{c{\_}ubyte}. +\end{classdesc*} + +\begin{classdesc*}{c_uint16} +Represents the C 16-bit unsigned int datatype. Usually an alias for +\class{c{\_}ushort}. +\end{classdesc*} + +\begin{classdesc*}{c_uint32} +Represents the C 32-bit unsigned int datatype. Usually an alias for +\class{c{\_}uint}. +\end{classdesc*} + +\begin{classdesc*}{c_uint64} +Represents the C 64-bit unsigned int datatype. Usually an alias for +\class{c{\_}ulonglong}. +\end{classdesc*} + +\begin{classdesc*}{c_ulong} +Represents the C \code{unsigned long} datatype. The constructor accepts an +optional integer initializer; no overflow checking is done. +\end{classdesc*} + +\begin{classdesc*}{c_ulonglong} +Represents the C \code{unsigned long long} datatype. The constructor +accepts an optional integer initializer; no overflow checking is +done. +\end{classdesc*} + +\begin{classdesc*}{c_ushort} +Represents the C \code{unsigned short} datatype. The constructor accepts an +optional integer initializer; no overflow checking is done. +\end{classdesc*} + +\begin{classdesc*}{c_void_p} +Represents the C \code{void *} type. The value is represented as +integer. The constructor accepts an optional integer initializer. +\end{classdesc*} + +\begin{classdesc*}{c_wchar} +Represents the C \code{wchar{\_}t} datatype, and interprets the value as a +single character unicode string. The constructor accepts an +optional string initializer, the length of the string must be +exactly one character. +\end{classdesc*} + +\begin{classdesc*}{c_wchar_p} +Represents the C \code{wchar{\_}t *} datatype, which must be a pointer to +a zero-terminated wide character string. The constructor accepts +an integer address, or a string. +\end{classdesc*} + +\begin{classdesc*}{HRESULT} +Windows only: Represents a \class{HRESULT} value, which contains success +or error information for a function or method call. +\end{classdesc*} + + +\subsubsection{structured data types\label{ctypes-structured-data-types}} + +\begin{classdesc}{Union}{*args, **kw} +Abstract base class for unions in native byte order. +\end{classdesc} + +\begin{classdesc}{BigEndianStructure}{*args, **kw} +Abstract base class for structures in \emph{big endian} byte order. +\end{classdesc} + +\begin{classdesc}{LittleEndianStructure}{*args, **kw} +Abstract base class for structures in \emph{little endian} byte order. +\end{classdesc} + +Structures with non-native byte order cannot contain pointer type +fields, or any other data types containing pointer type fields. + +\begin{classdesc}{Structure}{*args, **kw} +Abstract base class for structures in \emph{native} byte order. +\end{classdesc} + +Concrete structure and union types must be created by subclassing one +of these types, and at least define a \member{{\_}fields{\_}} class variable. +\code{ctypes} will create descriptors which allow reading and writing the +fields by direct attribute accesses. These are the + +\begin{memberdesc}{_fields_} +A sequence defining the structure fields. The items must be +2-tuples or 3-tuples. The first item is the name of the field, +the second item specifies the type of the field; it can be any +ctypes data type. + +For integer type fields, a third optional item can be given. It +must be a small positive integer defining the bit width of the +field. + +Field names must be unique within one structure or union. This is +not checked, only one field can be accessed when names are +repeated. + +It is possible to define the \member{{\_}fields{\_}} class variable \emph{after} +the class statement that defines the Structure subclass, this +allows to create data types that directly or indirectly reference +themselves: +\begin{verbatim} +class List(Structure): + pass +List._fields_ = [("pnext", POINTER(List)), + ... + ] +\end{verbatim} + +The \member{{\_}fields{\_}} class variable must, however, be defined before +the type is first used (an instance is created, \code{sizeof()} is +called on it, and so on). Later assignments to the \member{{\_}fields{\_}} +class variable will raise an AttributeError. + +Structure and union subclass constructors accept both positional +and named arguments. Positional arguments are used to initialize +the fields in the same order as they appear in the \member{{\_}fields{\_}} +definition, named arguments are used to initialize the fields with +the corresponding name. + +It is possible to defined sub-subclasses of structure types, they +inherit the fields of the base class plus the \member{{\_}fields{\_}} defined +in the sub-subclass, if any. +\end{memberdesc} + +\begin{memberdesc}{_pack_} +An optional small integer that allows to override the alignment of +structure fields in the instance. \member{{\_}pack{\_}} must already be +defined when \member{{\_}fields{\_}} is assigned, otherwise it will have no +effect. +\end{memberdesc} + +\begin{memberdesc}{_anonymous_} +An optional sequence that lists the names of unnamed (anonymous) +fields. \code{{\_}anonymous{\_}} must be already defined when \member{{\_}fields{\_}} +is assigned, otherwise it will have no effect. + +The fields listed in this variable must be structure or union type +fields. \code{ctypes} will create descriptors in the structure type +that allows to access the nested fields directly, without the need +to create the structure or union field. + +Here is an example type (Windows): +\begin{verbatim} +class _U(Union): + _fields_ = [("lptdesc", POINTER(TYPEDESC)), + ("lpadesc", POINTER(ARRAYDESC)), + ("hreftype", HREFTYPE)] + +class TYPEDESC(Structure): + _fields_ = [("u", _U), + ("vt", VARTYPE)] + + _anonymous_ = ("u",) +\end{verbatim} + +The \code{TYPEDESC} structure describes a COM data type, the \code{vt} +field specifies which one of the union fields is valid. Since the +\code{u} field is defined as anonymous field, it is now possible to +access the members directly off the TYPEDESC instance. +\code{td.lptdesc} and \code{td.u.lptdesc} are equivalent, but the former +is faster since it does not need to create a temporary \code{{\_}U} +instance: +\begin{verbatim} +td = TYPEDESC() +td.vt = VT_PTR +td.lptdesc = POINTER(some_type) +td.u.lptdesc = POINTER(some_type) +\end{verbatim} +\end{memberdesc} + +It is possible to defined sub-subclasses of structures, they inherit +the fields of the base class. If the subclass definition has a +separate``{\_}fields{\_}`` variable, the fields specified in this are +appended to the fields of the base class. + diff --git a/Lib/ctypes/test/test_cfuncs.py b/Lib/ctypes/test/test_cfuncs.py index 9d8db1f4894..fa858a66132 100644 --- a/Lib/ctypes/test/test_cfuncs.py +++ b/Lib/ctypes/test/test_cfuncs.py @@ -40,41 +40,49 @@ class CFunctions(unittest.TestCase): def test_short(self): self._dll.tf_h.restype = c_short + self._dll.tf_h.argtypes = (c_short,) self.failUnlessEqual(self._dll.tf_h(-32766), -10922) self.failUnlessEqual(self.S(), -32766) def test_short_plus(self): self._dll.tf_bh.restype = c_short + self._dll.tf_bh.argtypes = (c_byte, c_short) self.failUnlessEqual(self._dll.tf_bh(0, -32766), -10922) self.failUnlessEqual(self.S(), -32766) def test_ushort(self): self._dll.tf_H.restype = c_ushort + self._dll.tf_H.argtypes = (c_ushort,) self.failUnlessEqual(self._dll.tf_H(65535), 21845) self.failUnlessEqual(self.U(), 65535) def test_ushort_plus(self): self._dll.tf_bH.restype = c_ushort + self._dll.tf_bH.argtypes = (c_byte, c_ushort) self.failUnlessEqual(self._dll.tf_bH(0, 65535), 21845) self.failUnlessEqual(self.U(), 65535) def test_int(self): self._dll.tf_i.restype = c_int + self._dll.tf_i.argtypes = (c_int,) self.failUnlessEqual(self._dll.tf_i(-2147483646), -715827882) self.failUnlessEqual(self.S(), -2147483646) def test_int_plus(self): self._dll.tf_bi.restype = c_int + self._dll.tf_bi.argtypes = (c_byte, c_int) self.failUnlessEqual(self._dll.tf_bi(0, -2147483646), -715827882) self.failUnlessEqual(self.S(), -2147483646) def test_uint(self): self._dll.tf_I.restype = c_uint + self._dll.tf_I.argtypes = (c_uint,) self.failUnlessEqual(self._dll.tf_I(4294967295), 1431655765) self.failUnlessEqual(self.U(), 4294967295) def test_uint_plus(self): self._dll.tf_bI.restype = c_uint + self._dll.tf_bI.argtypes = (c_byte, c_uint) self.failUnlessEqual(self._dll.tf_bI(0, 4294967295), 1431655765) self.failUnlessEqual(self.U(), 4294967295)