I've been trying a few things with shedskin. So far I've
been amazed by what if can do! Thanks so much for creating
this software!
I'd like to use shedskin to make my python code run faster,
but I need support for __del__ for various data structures
implemented in c, like canvases, OpenGL texture maps, frame
buffer objects, etc.
I'm building a ui view archiecture in python to support writing
iOS/Android/OSX applications. A work in progress video is here:
This project is 5000 lines of python calling 20,000 lines of C to
do graphics, etc.
I've attached a .zip file with an example project that shows
what I'm trying to do. Having support for being able to
define my own __del__ method would be a wonderful thing.
Please let me know if you have any comments or questions.
Paul Haeberli
To compile and run this example, do this:
shedskin -L lib imageproc.py
make
./imageproc
to remove the files generated do:
rm Makefile
rm frame.tga
rm red.tga
rm saturate.tga
rm shift.tga
rm small.tga
rm imageproc
rm imageproc.cpp
rm imageproc.hpp
The module libgfx support calls to alloc and free
canvases - arrays of 32 bit ints that hold image data.
canvas *cannew(int sizex, int sizey)
{
canvas *c;
c = (canvas *)malloc(sizeof(canvas));
c->sizex = sizex;
c->sizey = sizey;
c->data = (unsigned int *)malloc(sizex*sizey*sizeof(unsigned int));
nalloc++;
return c;
}
void canfree(canvas *c)
{
if(!c)
return;
free(c->data);
free(c);
nalloc--;
}
Image processing happens in C like this:
void cansaturate(canvas *c, float sat)
{
int npix = c->sizex*c->sizey;
unsigned int *lptr = c->data;
while(npix--) {
int r = RVAL(*lptr);
int g = GVAL(*lptr);
int b = BVAL(*lptr);
int lum = ILUM(r,g,b);
*lptr++ = CPACK(pixlerp(lum,r,sat),pixlerp(lum,g,sat),pixlerp(lum,b,sat),255);
}
}
Here's some of my python code that supports canvas in python. The python
code keeps an int with a pointer to the c canvas data structure in self.can
I'd really like __del__ to work so the c data sctructures can be freed, etc.
class canvas():
def __init__(self):
def init(self):
self.rect = rectsize(self.sizex, self.sizey)
self.readonly = False
self.diagsize = float(math.sqrt(self.sizex*self.sizex+self.sizey*self.sizey))
self.units = float(max(self.sizex, self.sizey))
self.origin = point(0.0,0.0)
def initsize(self, sizex, sizey):
self.can = libgfx.gfx_cannew(sizex, sizey)
self.sizex = sizex
self.sizey = sizey
self.nchans = 4
self.init()
def initpointer(self, ptr):
self.can = ptr
size = libgfx.gfx_cansize(self.can)
self.sizex = size[0]
self.sizey = size[1]
self.nchans = size[2]
self.init()
def __str__(self):
return "canvas: size: " + str(self.rect.sizex) + "," + str(self.rect.sizey) + " nchans: " + str(self.nchans)
def __del__(self):
print "canvas: DESTRUCT"
print self
if self.can != 0:
libgfx.gfx_canfree(self.can) # this is never called by shedskin
self.can = 0
def setreadonly(self, ro):
self.readonly = ro
def touched(self):
if self.readonly:
print "Error: Canvas is readonly"
print self
def tofile(self, filename):
libgfx.gfx_cantofile(self.can, filename)
return self
# misc utils
def putpix(self, x, y, pix):
libgfx.gfx_canputpix(self.can, x, y, pix)
def getpix(self, x, y):
return libgfx.gfx_cangetpix(self.can, x, y)
def saturate(self, sat):
self.touched()
libgfx.gfx_cansaturate(self.can, sat)
return self
def shift(self, shiftx, shifty): # pix dim
c = canvas()
c.initpointer(libgfx.gfx_canshift(self.can, int(shiftx), int(shifty)))
c.origin.x = self.origin.x - shiftx
c.origin.y = self.origin.y - shifty
return c
def frame(self, r, g, b, a, width): # pix dim
c = canvas()
c.initpointer(libgfx.gfx_canframe(self.can, r, g, b, a, width))
c.origin.x = self.origin.x + width
c.origin.y = self.origin.y + width
return c
def subimage(self, r): # pix dim
c = canvas()
c.initpointer(libgfx.gfx_cansubimg(self.can, int(r.orgx), int(r.orgy), int(r.sizex), int(r.sizey)))
c.origin.x = self.origin.x - int(r.orgx)
c.origin.y = self.origin.y - int(r.orgy)
return c
def zoom(self, zoomx, zoomy):
c = canvas()
c.initpointer(libgfx.gfx_canzoom(self.can, zoomx, zoomy))
c.origin.x = c.origin.x * zoomx
c.origin.y = c.origin.y * zoomy
return c
def clone(self):
c = canvas()
c.initpointer(libgfx.gfx_canclone(self.can))
c.origin = self.origin
return c
def new(self):
c = canvas()
c.initpointer(libgfx.gfx_cannew(self.rect.sizex,self.rect.sizey))
c.origin = self.origin
return c
def blend(self, c, r, g, b, a):
self.touched()
libgfx.gfx_canblend(self.can, c.can, r, g, b, a)
return self
def mult(self, c):
self.touched()
libgfx.gfx_canmult(self.can, c.can)
return self
def scalergba(self, r, g, b, a):
self.touched()
libgfx.gfx_canscalergba(self.can, r, g, b, a)
return self
def clear(self, r, g, b, a):
self.touched()
libgfx.gfx_canclear(self.can, r, g, b, a)
return self
def canvasfromfile(filename):
can = canvas()
ptr = libgfx.gfx_canfromfile(filename)
can.initpointer(ptr)
return can
def canvasnew(sizex, sizey):
can = canvas()
can.initsize(sizex, sizey)
return can
def canvasnalloc():
return libgfx.gfx_cannalloc()