aholkner  committed 0be2e49

Filled out major sections of manual; bug fixes to documentation
generation and version checking.

  • Participants
  • Parent commits 9e87430
  • Branches ctypes-soc

Comments (0)

Files changed (5)

File SDL/

 from SDL.error import *
 from import *
 from SDL.keyboard import *
-from SDL.keysym import *
 from SDL.mouse import *
 from SDL.quit import *
 from SDL.rwops import *

File SDL/

     _SDL_GetKeyRepeat(byref(delay), byref(interval))
     return delay.value, interval.value
-_SDL_GetKeyState = SDL.dll.private_function('SDL_GetKeyRepeat',
+_SDL_GetKeyState = SDL.dll.private_function('SDL_GetKeyState',

File doc/manual.txt
 :revision: 0.03
-:date: 11 June 2006
+:date: 12 June 2006
 :copyright: Copyright (c) 2006 Alex Holkner.
 The following sections detail the general differences you can expect to
+The preferred way to use SDL-ctypes is with::
+    from SDL import *
+This follows the convention of PyOpenGL, and allows you to call SDL
+functions in the same way as the C library.  The actual package is
+composed of several modules such as ``SDL.cdrom``, ````, and
+so on.  All functions and structures from each module are imported
+directly into the SDL namespace for convenience.
+The API documentation lists functions in both their originating module
+and the SDL module for readability.
 Error checking
+Many SDL functions return an error code (the actual code depends on the
+function: some return 0 on error, others return -1 on error).  SDL-ctypes
+hides this detail from the application and will check return codes itself.
+When an error code is returned from the SDL library, an ``SDL_Exception``
+is raised.  The message it contains is the return value of ``SDL_GetError``.
+In general this means you can leave out error checking code in your
+application, or use try/except clauses where necessary.
 Return by reference
         int SDL_PeepEvents(SDL_Event *events, int numevents, int action, int
-   In SDL-ctypes the array of events is returned as a list:
+   In SDL-ctypes the array of events is returned as a list::
         SDL_PeepEvents(numevents, action, mask) -> list of SDL_Event
 Large arrays
-Here are a few samples of reStructuredText that you may find handy.
+There are times when you need to access and manipulate large arrays
+of data in SDL.  For example, ``SDL_SetGammaRamp`` in C takes
+three arrays of integers.  The ``SDL_Surface.pixels`` attribute in C
+is a void pointer to a large array of pixel data.
+In SDL-ctypes the ``SDL_array`` abstraction is used to represent
+large arrays of data, allowing you to choose which format you would
+like the data in.
+For example, to access the surface pixels as an instance of ``SDL_array``::
+    surface = SDL_SetVideoMode(640, 480, 32, 0)
+    pixels = surface.pixels
+``SDL_array`` implements the usual slicing and indexing operators so you
+can access the data element-wise::
+    # Set the third pixel to red
+    pixels[3] = SDL_MapRGBColor(surface.format, 255, 0, 0)
+    # Set all pixels to white
+    white = SDL_MapRGBColor(surface.format, 255, 255, 255)
+    for i in range(len(pixels)):
+        pixels[i] = white
+    # Equivalent to
+    pixels[:] = [white] * len(pixels)
+You can also access the data as a NumPy array, if it is installed::
+    pixels = surface.pixels.as_numpy()
+The resultant array is mapped directly to the SDL buffer, so updates
+are immediate::
+    # Set all pixels to white
+    pixels[:] = [white] * len(pixels)
+    # Add one to all pixel values:
+    numpy.add(pixels, 1)
+Using NumPy is substantially faster than plain Python code.
+If you are using another library that uses ctypes, you can pass it
+the raw buffer as a pointer::
+    # Get the ctypes buffer pointer
+    p = surface.pixels.as_ctypes()
+So far all demonstrated operations have been on the pixel type; for
+example if using a 32-bit buffer, each element in the array is an
+integer representing the complete buffer.  You can also access the
+raw bytes of the buffer::
+    bytes = surface.pixels.as_bytes()
+If you know what you're doing, you can manipulate the buffer in the
+same way::
+    # Zero out the third byte of the buffer.
+    bytes[3] = 0 
+You can access the byte buffer as a NumPy array or ctypes pointer in
+the same way::
+    bytes = surface.pixels.as_bytes().as_numpy()
+    bytes = surface.pixels.as_bytes().as_ctypes()
+You have already seen that ``SDL_Surface.pixels`` is an ``SDL_array``.
+Some functions also return ``SDL_array``, which can be manipulated
+in the same way::
+    red, green, blue = SDL_GetGammaRamp()
+    red = red.as_numpy()
+    red[:] = numpy.zeros(len(red))
+Any sequence, ctypes pointer or NumPy array can be passed as an argument
+to a function expecting ``SDL_array``::
+    # red is now a NumPy array; green is still SDL_array; blue is a list
+    SDL_SetGammaRamp(red, green, [0] * 256)
+Functions accepting SDL_array also accept any sequence, ctypes pointer
+or NumPy array of a byte buffer::
+    SDL_SetGammaRamp(red, green.as_bytes(), [0] * 256 * 2)
+``SDL_RWops`` is a structure in SDL that describes a read/write interface
+to an arbitrary object.  For example, the ``SDL_Load_BMP_RW`` function
+can create an ``SDL_Surface`` from any source.
+Several functions from SDL have been included in SDL-ctypes for creating
+``SDL_RWops`` from files::
+    rw = SDL_RWFromFile('sample.bmp', 'rb')
+You can also create an SDL_RWops from any Python file-like object that
+provides read, write, seek and close methods::
+    f = open('sample.bmp')
+    rw = SDL_RWFromObject(f)
+For example, you could use this functionality to load a bitmap directly
+from a ZIP archive or remote URL.
+Version compatibility
+SDL-ctypes can be used with any SDL shared library from version 2.1.1 
+onwards.  Differences between these versions are handled transparently
+where possible (e.g., the difference in layout between structures).
+If you call a function or access a structure member that doesn't exist
+in the version that was linked at runtime, ``SDL_NotImplementedError``
+will be raised.
+You can check the version of the runtime library with ``SDL_Linked_Version``.
 Tools and process
+Releasing a snapshot
+1. Increment revision numbers in ```` and ``doc/manual.txt``, and
+   ensure ``CHANGELOG`` is up to date.
+2. Generate user documentation (requires ``mkhowto`` from the Python source
+   and `Python LaTeX Writer
+   <>`_::
+      python manual
+3. Generate API documentation (requires `Epydoc
+   <>`_ 3.0 alpha or later)::
+      python apidoc
+4. Generate snapshot::
+      python sdist
+How API documentation is generated
+EpyDoc generates HTML pages by both parsing source files and by
+importing the modules and introspecting them.  When EpyDoc is run
+on the SDL package it misses most functions, as they are created
+procedurally with ``SDL.dll.function``.  The parser misses them as
+they look like variable assignments, and the introspector misses them
+as the underlying function is declared in another module.
+The script ``support/`` creates a package in ``build_doc``
+by introspecting the SDL module and writing the function definitions
+and their docstrings in the standard form.  EpyDoc is then run over
+the ``build_doc`` directory to generate useful API documentation.
+Run it with::
+    python support/ build_doc/
+(it is also run automatically by within the ``apidoc`` commmand.)
+Detecting changes in SDL revisions
+``support/`` can be used to checkout consecutive releases
+of libsdl and diff each version against its predecessor.  The results
+are written to ``support/diff_1.2.x.txt``, where x is the newer version.
+When a new version of SDL is released, add the revision number to
+the script and re-run it.  Examine the generated report for added or
+changed function prototypes and structures, and make the appropriate
+changes to SDL-ctypes.
     def run(self):'python support/ build_doc/',
-        os.makedirs(apidoc_dir)
+        try:
+            os.makedirs(apidoc_dir)
+        except:
+            pass
         olddir = os.getcwd()
         os.chdir('build_doc')'epydoc --no-private --html --no-sourcecode ' + \
         olddir = os.getcwd()
         os.chdir(doc_dir)'%s manual.txt > manual.tex' % latex_writer, shell=True)
-'%s --split=3 manual.tex' % mkhowto, shell=True)
+'%s --split=4 manual.tex' % mkhowto, shell=True)

File support/

     print >> file
 def write_class(cls, file):
-    if ctypes.Structure in cls.__bases__:
+    if ctypes.Structure in cls.__bases__ or \
+       ctypes.Union in cls.__bases__:
         print >> file, 'class %s:' % cls.__name__
         print >> file, '    %s' % repr(cls.__doc__ or '')
         for field in cls._fields_:
             if field[0] != '_':
                 print >> file, '    %s = None' % field[0]
+    else:
+        print >> file, '%s' % inspect.getsource(cls)
 def write_variable(child_name, child, file):
     print >> file, '%s = %s' % (child_name, repr(child))
             write_class(child, f)
         elif inspect.ismodule(child):
-        elif module in (SDL, SDL.constants, SDL.keysym):
+        elif module in (SDL, SDL.constants):
             write_variable(child_name, child, f)
 def module_file(module_name):
-    if module_name[:3] != 'SDL' or module_name in ('SDL.dll', 'SDL.array'):
+    if module_name[:3] != 'SDL' or module_name in ('SDL.dll', ):
         return None
     if module_name in modules: