Commits

Anonymous committed 6b48926

Fast string buffer conversion; buffer retention in SDL_CreateRGBBufferFrom

Comments (0)

Files changed (7)

      - `count`: int
      - `ctype`: type
 
+    :rtype: object, ctypes.Array
+    :return: (ref, array), where ref is an object that must be retained
+        by the caller for as long as the array is used.
     '''
 
+    ref = values
+
     # Convert SDL_array instances to ctypes array
     if isinstance(values, SDL_array):
         values = values.as_ctypes()
     # Cast ctypes array to correct type if necessary
     if isinstance(values, Array):
         if values._type_ is ctype:
-            return values
+            return ref, values
         else:
-            return cast(values, POINTER(ctype * count)).contents
+            return ref, cast(values, POINTER(ctype * count)).contents
 
-    # Convert string bytes to integers
+    # Convert string bytes to array
     if type(values) == str:
-        values = [ord(c) for c in values]
+        ref = create_string_buffer(values)
+        return ref, cast(ref, POINTER(ctype * count)).contents
 
     # Otherwise assume sequence
-    return (ctype * count)(*values)
+    ar = (ctype * count)(*values)
+    return ar, ar
      - `volume`: int
 
     '''
-    dst = SDL.array.to_ctypes(dst, len(dst), c_ubyte)
-    src = SDL.array.to_ctypes(src, len(src), c_ubyte)
+    dstref, dst = SDL.array.to_ctypes(dst, len(dst), c_ubyte)
+    srcref, src = SDL.array.to_ctypes(src, len(src), c_ubyte)
     if len(dst) < length:
         raise TypeError, 'Destination buffer too small'
     elif len(src) < length:
 
     :rtype: `Mix_Chunk`
     '''
-    mem = SDL.array.to_ctypes(mem, len(mem), c_ubyte)
+    ref, mem = SDL.array.to_ctypes(mem, len(mem), c_ubyte)
     return _Mix_QuickLoad_WAV(mem)
 
 _Mix_QuickLoad_RAW = _dll.private_function('Mix_QuickLoad_RAW',
     :rtype: `Mix_Chunk`
     '''
     l = len(mem)
-    mem = SDL.array.to_ctypes(mem, len(mem), c_ubyte)
+    ref, mem = SDL.array.to_ctypes(mem, len(mem), c_ubyte)
     return _Mix_QuickLoad_RAW(mem, l)
 
 Mix_FreeChunk = _dll.function('Mix_FreeChunk',
 
     :rtype: `SDL_Cursor`
     '''
-    data = SDL.array.to_ctypes(data, len(data), c_ubyte)
-    mask = SDL.array.to_ctypes(mask, len(mask), c_ubyte)
+    dataref, data = SDL.array.to_ctypes(data, len(data), c_ubyte)
+    maskref, mask = SDL.array.to_ctypes(mask, len(mask), c_ubyte)
     return _SDL_CreateCursor(data, mask, w, h, hot_x, hot_y)
 
 SDL_SetCursor = SDL.dll.function('SDL_SetCursor',
 
     :since: Not yet released in SDL_sound
     '''
-    data = SDL.array.to_ctypes(data, len(data), c_ubyte)
+    ref, data = SDL.array.to_ctypes(data, len(data), c_ubyte)
     return _Sound_NewSampleFromMem(data, len(data), ext, desired, bufferSize)
 
 Sound_NewSampleFromFile = _dll.function('Sound_NewSampleFromFile',
             return SDL.array.SDL_array(self._pixels, count, sz)
         raise AttributeError, name
 
-    def __setattr__(self, attr, value):
-        raise AttributeError, '%s is read only' % attr
-
-
 def SDL_MUSTLOCK(surface):
     '''Evaluates to true if the surface needs to be locked before access.
 
       - `screen`: `SDL_Surface`
       - `rects`: list of `SDL_Rect`
     '''
-    ar = SDL.array.to_ctypes(rects, len(rects), SDL_Rect)
+    ref, ar = SDL.array.to_ctypes(rects, len(rects), SDL_Rect)
     _SDL_UpdateRects(screen, len(rects), ar)
 
 SDL_UpdateRect = SDL.dll.function('SDL_UpdateRect',
     '''
     rar = gar = bar = None
     if red:
-        rar = SDL.array.to_ctypes(red, 256, c_ushort)
+        rref, rar = SDL.array.to_ctypes(red, 256, c_ushort)
     if green:
-        gar = SDL.array.to_ctypes(green, 256, c_ushort)
+        gref, gar = SDL.array.to_ctypes(green, 256, c_ushort)
     if blue:
-        bar = SDL.array.to_ctypes(blue, 256, c_ushort)
+        bref, bar = SDL.array.to_ctypes(blue, 256, c_ushort)
     result = _SDL_SetGammaRamp(rar, gar, bar)
     if result != 0:
         raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
     :rtype: int
     :return: 1 if all colors were set as passed, otherwise 0.
     '''
-    ar = SDL.array.to_ctypes(colors, len(colors), SDL_Color)
+    ref, ar = SDL.array.to_ctypes(colors, len(colors), SDL_Color)
     return _SDL_SetColors(surface, ar, firstcolor, len(colors))
 
 _SDL_SetPalette = SDL.dll.private_function('SDL_SetPalette',
       - `colors`: sequence or SDL_array of `SDL_Color`
       - `firstcolor`: int; the first color index to set.
     '''
-    ar = SDL.array.to_ctypes(colors, len(colors), SDL_Color)
+    ref, ar = SDL.array.to_ctypes(colors, len(colors), SDL_Color)
     result = _SDL_SetPalette(surface, flags, ar, firstcolor, len(colors))
     if result != 1:
         raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
 
     :rtype: `SDL_Surface`
     '''
+    len_pixels = len(pixels)
     if len(pixels) == pitch * 8 / depth * height:
         # pixel array?
         if depth == 8:
-            ar = SDL.array.to_ctypes(pixels, len(pixels), c_ubyte)
+            ref, ar = SDL.array.to_ctypes(pixels, len(pixels), c_ubyte)
         elif depth == 16:
-            ar = SDL.array.to_ctypes(pixels, len(pixels), c_ushort)
+            ref, ar = SDL.array.to_ctypes(pixels, len(pixels), c_ushort)
         elif depth == 32:
-            ar = SDL.array.to_ctypes(pixels, len(pixels), c_uint)
+            ref, ar = SDL.array.to_ctypes(pixels, len(pixels), c_uint)
     elif len(pixels) == pitch * height:
         # byte array
-        ar = SDL.array.to_ctypes(pixels, len(pixels), c_ubyte)
+        ref, ar = SDL.array.to_ctypes(pixels, len(pixels), c_ubyte)
     else:
         raise TypeError, 'Length of pixels does not match given dimensions.'
 
-    return _SDL_CreateRGBSurfaceFrom(cast(ar, POINTER(c_ubyte)),
+    surface = _SDL_CreateRGBSurfaceFrom(cast(ar, POINTER(c_ubyte)),
         width, height, depth, pitch, Rmask, Gmask, Bmask, Amask)
+    surface._buffer_ref = ref
+    return surface
 
 SDL_FreeSurface = SDL.dll.function('SDL_FreeSurface',
     '''Free an RGB Surface.
 
     '''
     if mask:
-        mask = SDL.array.to_ctypes(mask, (icon.w * icon.h + 7) / 8, c_ubyte)
+        ref, mask = \
+            SDL.array.to_ctypes(mask, (icon.w * icon.h + 7) / 8, c_ubyte)
     _SDL_WM_SetIcon(icon, mask)
 
 SDL_WM_IconifyWindow = SDL.dll.function('SDL_WM_IconifyWindow',

test/interop_pil.py

 
         # Caution: keep the ctypes array ("data") as a local var during
         # blitting, otherwise the pixel data will be free'd early
-        s = image.tostring()
-        data = SDL.array.to_ctypes(s, len(s), c_ubyte)
+        #s = image.tostring()
+        #sb = create_string_buffer(s)
+        #data = cast(sb, POINTER(c_ubyte*len(s))).contents
+        #data = SDL.array.to_ctypes(s, len(s), c_ubyte)
 
         # This alternative also works
         #s = [c[0] | (c[1] << 8) | (c[2] << 16) for c in image.getdata()]
         #data = SDL.array.to_ctypes(s, len(s), c_uint)
 
-        surface = SDL_CreateRGBSurfaceFrom(data,
+        surface = SDL_CreateRGBSurfaceFrom(image.tostring(),
             image_width, image_height, 32, image_width * 4,
             0x000000ff,
             0x0000ff00,