=============================== README: ctypes code generation =============================== .. _REST quickref (only for the editor): http://docutils.sourceforge.net/docs/user/rst/quickstart.html This document describes the ctypes code generator. The generator converts declarations in C header files into executable Python code: enums, structs, unions, function declarations, com interfaces, and preprocessor definitions. **The code generator is brand new and still experimental, although hopefully better than in the 0.9.5 release.** .. contents:: Overview ======== Creating wrappers for C header file(s) is a two step process. First, the ``h2xml.py`` script runs GCC-XML_ over the include file(s), creating a XML file containing declarations and definitions. Second, the ``xml2py.py`` script parses the XML files and creates Python code containing all or a subset of these definitions. Python code is generated for C enums, structure, unions, typedefs and function declarations. Also included are preprocessor definitions, as far as they can be converted to valid Python code. It is possible to filter the output so that only a subset of the definitions are converted, so it is either possible to generate a complete Python module wrapping a shared library, or the generator can be used to create snippets of Python code which can be pasted into a manually written module. Requirements ============ GCC-XML_ (from http://www.gccxml.org/) is required to parse C header files into an XML description. **Unfortunately the latest official version 0.6.0 does not fulfill the ctypes code generator requirements.** For windows, you can download a prebuild `GCC-XML windows installer`_ from `the ctypes download page`_ (this is an unofficial release). Please note that even the *installation* of GCC-XML requires that MSVC 6, 7, or 7.1 is installed on your system, because it needs the system header files. For other platforms you must `get the development version from CVS`_ and `build GCC-XML from source`_. .. _the ctypes download page: http://sourceforge.net/project/showfiles.php?group_id=71702 .. _GCC-XML windows installer: http://sourceforge.net/project/showfiles.php?group_id=71702&package_id=71318&release_id=313813 .. _GCC-XML: http://www.gccxml.org/ .. _build GCC-XML from source: http://www.gccxml.org/HTML/Install.html .. _get the development version from CVS: http://www.gccxml.org/HTML/Download.html Changes in the ctypes 0.9.6 release =================================== - ``h2xml.py`` doesn't try to find preprocessor definitions by default anymore. Can be changed with the new ``-c`` or ``--cpp-symbols`` flag. - Added ``-k`` option to ``h2xml.py`` to not delete temporary files. - Better error output if the compilation fails. - ``h2xml.py`` can load an optional local configuration file from the current directory - several bugs in the gccxml installer plus one bug in gccxml has been fixed, and the gccxml installer snapshot has been rebuilt. Usage examples ============== Here are several examples that show how to call the ``h2xml.py`` and ``xml2py.py`` scripts, and the code they generate. The output has sometimes been cleaned up a bit, for clarity. Generally, the codegenerator creates a lot of comments pointing to the C header file. This is useful to quickly look up the C source code. Parse the windows header files (this may take a while), and include preprocessor definitions in the xml file:: C:\>python h2xml.py windows.h -o windows.xml -q -c C:\> Generate code for the ``RECT`` structure:: C:\>xml2py.py windows.xml -s RECT from ctypes import * LONG = c_long class tagRECT(Structure): pass RECT = tagRECT tagRECT._fields_ = [ ('left', c_long), ('top', c_long), ('right', c_long), ('bottom', c_long), ] assert sizeof(tagRECT) == 16, sizeof(tagRECT) assert alignment(tagRECT) == 4, alignment(tagRECT) C:\> Generate the ``MB_xxx`` constants, which are flags used for the ``MessageBox`` function - since these are #define'd symbols this works only when the xml file includes preprocessor definitions:: c:\>python xml2py.py windows.xml -r MB_.* # generated by 'xml2py.py' # flags 'windows.xml -r MB_.*' MB_USERICON = 128 MB_DEFBUTTON3 = 512 MB_USEGLYPHCHARS = 4 MB_ABORTRETRYIGNORE = 2 MB_ICONASTERISK = 64 MB_ICONINFORMATION = MB_ICONASTERISK MB_ICONHAND = 16 MB_ICONERROR = MB_ICONHAND MB_ICONEXCLAMATION = 48 MB_ICONWARNING = MB_ICONEXCLAMATION MB_RIGHT = 524288 MB_SYSTEMMODAL = 4096 MB_ICONQUESTION = 32 MB_APPLMODAL = 0 MB_OK = 0 MB_TYPEMASK = 15 MB_MODEMASK = 12288 MB_TASKMODAL = 8192 MB_OKCANCEL = 1 MB_RETRYCANCEL = 5 MB_DEFAULT_DESKTOP_ONLY = 131072 MB_RTLREADING = 1048576 MB_PRECOMPOSED = 1 MB_DEFBUTTON1 = 0 MB_DEFMASK = 3840 MB_DEFBUTTON2 = 256 MB_YESNOCANCEL = 3 MB_CANCELTRYCONTINUE = 6 MB_HELP = 16384 MB_ICONMASK = 240 MB_SETFOREGROUND = 65536 MB_TOPMOST = 262144 MB_COMPOSITE = 2 MB_DEFBUTTON4 = 768 MB_YESNO = 4 MB_ERR_INVALID_CHARS = 8 MB_NOFOCUS = 32768 MB_ICONSTOP = MB_ICONHAND MB_MISCMASK = 49152 C:\> Generate code for the ``RegisterClass`` function, note how this pulls in a lot of types (if you want code compatible with Python 2.3 don't use the ``-d`` flag):: C:\>python xml2py.py windows.xml -w -s RegisterClass -d # generated by 'xml2py' # flags 'windows.xml -w -s RegisterClass' from ctypes import * from ctypes import decorators WORD = c_ushort ATOM = WORD class tagWNDCLASSA(Structure): pass WNDCLASSA = tagWNDCLASSA @ decorators.stdcall(ATOM, 'user32', [POINTER(WNDCLASSA)]) def RegisterClassA(p1): return RegisterClassA._api_(p1) RegisterClass = RegisterClassA UINT = c_uint LONG_PTR = c_long LRESULT = LONG_PTR WNDPROC = WINFUNCTYPE(LRESULT, c_void_p, c_uint, c_uint, c_long) PVOID = c_void_p HANDLE = PVOID HINSTANCE = HANDLE HICON = HANDLE HCURSOR = HICON HBRUSH = HANDLE CHAR = c_char LPCSTR = POINTER(CHAR) tagWNDCLASSA._fields_ = [ ('style', UINT), ('lpfnWndProc', WNDPROC), ('cbClsExtra', c_int), ('cbWndExtra', c_int), ('hInstance', HINSTANCE), ('hIcon', HICON), ('hCursor', HCURSOR), ('hbrBackground', HBRUSH), ('lpszMenuName', LPCSTR), ('lpszClassName', LPCSTR), ] assert sizeof(tagWNDCLASSA) == 40, sizeof(tagWNDCLASSA) assert alignment(tagWNDCLASSA) == 4, alignment(tagWNDCLASSA) Generate code for the ``ICreateErrorInfo`` com interface. This example uses the ``-m`` command line flag, and the generated code imports several symbols from the specified ``ctypes.com`` module. Note that the ``_iid_`` member of the interface cannot be created by the code generator, but the generated comments allows to quickly locate the header file and patch this manually:: C:\sf\ctypes\ctypes\wrap>xml2py windows.xml -s ICreateErrorInfo -m ctypes.com # generated by 'xml2py' # flags 'windows.xml -s ICreateErrorInfo -m ctypes.com' from ctypes import * from ctypes.com import IUnknown from ctypes.com import GUID class ICreateErrorInfo(IUnknown): _iid_ = GUID('{}') # please look up iid and fill in! # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 5366 pass from ctypes.com import HRESULT from ctypes.com import GUID WCHAR = c_wchar OLECHAR = WCHAR LPOLESTR = POINTER(OLECHAR) from ctypes.com import DWORD from ctypes.com import STDMETHOD ICreateErrorInfo._methods_ = IUnknown._methods + [ # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 5366 STDMETHOD(HRESULT, 'SetGUID', [POINTER(GUID)]), STDMETHOD(HRESULT, 'SetSource', [LPOLESTR]), STDMETHOD(HRESULT, 'SetDescription', [LPOLESTR]), STDMETHOD(HRESULT, 'SetHelpFile', [LPOLESTR]), STDMETHOD(HRESULT, 'SetHelpContext', [DWORD]), ] Create a Python module ``win_lean.py`` containing wrappers for the 'lean' windows api, this creates a fairly large file:: C:\>python h2xml.py windows.h -D WIN32_LEAN_AND_MEAN -D NO_STRICT -o win_lean.xml -q C:\>python xml2py.py win_lean.xml -w -o win_lean.py Create a Python module ``SDL.py`` containing wrappers for the ``SDL`` library. To work around a problem GCC-XML has with a certain construct in the SDL header files on Windows, you must define the ``SDLCALL`` macro to an empty value:: C:\>python h2xml.py SDL.h -I SDL\include -D SDLCALL= -o SDL.xml -q C:\>python xml2py.py SDL.xml -o SDL.py -l SDL.dll C:\> On linux, the ``SDL.py`` module could be created in this way - both the location of the include file and the name of the shared library is different:: thomas@linux:~/ctypes/wrap> locate SDL.h /usr/include/SDL/SDL.h thomas@linux:~/ctypes/wrap> python h2xml.py SDL/SDL.h -o SDL.xml -q thomas@linux:~/ctypes/wrap> python xml2py.py SDL.xml -o SDL.py -l libSDL.so thomas@linux:~/ctypes/wrap> ls -l SDL.py -rw-r--r-- 1 thomas users 95772 2004-10-26 02:23 SDL.py thomas@linux:~/ctypes/wrap> The h2xml.py script =================== ``h2xml.py`` lets you specify the names of the header files to parse, the name of the XML output file, and a few options which are passed to GCC-XML. The ``-D``, ``-E``, and ``-I`` flags may occur several times. ``-h, --help`` Print a short usage summary and exit. ``-q, --quiet`` Run in quiet mode. The default mode is verbose, ``h2xml.py`` prints what it is currently doing. ``-D name[=value]`` This flag defines a preprocessor name. ``-U name`` This flag undefines a preprocessor name. ``-I directory`` This flag defines an additional include directory. ``-o xmlfile`` This flag specifies name and path of the XML output file. ``-c, --cpp-symbols`` Run additional magic to include #define symbols in the xml output. Depending on the madness in the header files this may or may not work. ``-k`` Do not delete temporary files created - this may be useful to find compilation problems. The h2xml.cfg configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you enable preprocessor definition processing with the ``-c`` flag, it is possible that you get compiler errors on certain symbols. In this case, it is needed to exclude those symbols by writing in local configuration file named ``h2xml.cfg`` in the current directory. The configuration file sections are named after ``sys.platform``, and it allows to specify the symbols to exclude by names or by regular expressions:: # h2xml.cfg # # config file for h2xml script # # sections should be named after 'sys.platform' # options supported are: # 'excluded' - names of preprocessor symbols to exclude, # separated by whitespace # 'excluded_re' - regular expressions, separated by whitespace, matching # cpp symbols to exclude # See the documentation of the standard Python ConfigParser module # for maore information on the file format. [win32] excluded = foo bar excluded_re = spam.* .*spam [cygwin] excluded = excluded_re = [linux2] excluded = excluded_re = [darwin] excluded = excluded_re = [freebsd5] excluded = excluded_re = The xml2py.py script ==================== ``-h, --help`` Print a short usage summary and exit. ``-d`` Use Python 2.4 decorators for wrapped functions. ``-k[d][e][f][m][s][t]`` Specifies the kind of types to include in the output: ``d`` - simple preprocessor definitions: #define ``e`` - enumerations ``f`` - function declarations ``m`` - preprocessor macros taking parameters: #define (parameters) something ``s`` - structures and unions ``t`` - typedefs ``-l sharedlib`` specify shared library to search for exported functions. ``-m module`` specifies a Python module containing symbols that will be imported instead of generated. ``-o outputfile`` name of the output file containing Python code. If not specified, the code is printed to standard output. ``-r regular_expression`` regular expression specifying names of symbols to include. ``-s symbol`` name of symbol to include. ``-v`` verbose mode: prints a short summary of types generated. ``-w`` windows only: add all standard windows dlls to the list of shared libraries searched for functions. Note that specifying the ``-k``, ``-s``, and ``-r`` flags create a start set of type declarations, the generated code, however, may also contain other types. If, for example, the code for an external function is generated, code for the argument and return types is also needed. Also note that code for function declarations is only created when ``xml2py.py`` can locate the function in one of the shared libraries specified with ``-l`` or ``-w``. Getting Help ============ If you have questions or need assistance with *ctypes* or the code generator, please `post a message`_ to the `ctypes-users mailing list`_. .. _post a message: mailto:ctypes-users@lists.sourceforge.net .. _ctypes-users mailing list: http://lists.sourceforge.net/lists/listinfo/ctypes-users .. Local Variables: mode: indented-text indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 compile-command: "make" End: