some work on the new Python binding

This commit is contained in:
John Cupitt 2011-12-23 15:20:54 +00:00
parent 73465109b7
commit 39e92f8f1b
6 changed files with 99 additions and 12 deletions

8
TODO
View File

@ -1,3 +1,11 @@
- python/* is too old, keep for reference, but we need to use the
introspection stuff to get current gobject bindings
look at that brancg again
- foreign docs come up as "VipsForeignSave", annoying, why?
- we can no longer have round brackets in filenames, argh

View File

@ -2,7 +2,7 @@ Experimental Python binding using ctypes
The current Python binding uses swig to wrap the C++ interface. This causes
problems on Windows, since compiling all of the DLLs correctly to work with
the various python binaries is painful, and makes the bainding very large.
the various python binaries is painful, and makes the binding very large.
The idea here is to use ctypes to make a binding that's just Python and which
directly wraps the C API. The new vips8 C API is much more wrapper-friendly,

View File

@ -5,6 +5,7 @@ import gc
import gobject
import vipsobject
import vipsimage
logging.basicConfig(level = logging.DEBUG)
@ -21,22 +22,34 @@ a = vipsimage.VipsImage('/home/john/pics/healthygirl.jpg')
print 'width =', a.width()
print 'height =', a.height()
print 'bands =', a.bands()
print 'format =', vipsimage.VipsBandFormat.name(a.format())
print 'coding =', vipsimage.VipsCoding.name(a.coding())
print 'interpretation =', vipsimage.VipsInterpretation.name(a.interpretation())
print 'format = %d - %s' % (a.format(),
vipsimage.VipsBandFormat.name(a.format()))
print 'coding = %d - %s' % (a.coding(),
vipsimage.VipsCoding.name(a.coding()))
print 'interpretation = %d - %s' % (a.interpretation(),
vipsimage.VipsInterpretation.name(a.interpretation()))
print 'xres =', a.xres()
print 'yres =', a.yres()
print 'xoffset =', a.xoffset()
print 'yoffset =', a.yoffset()
# should raise an error
a = vipsimage.VipsImage('banana')
try:
a = vipsimage.VipsImage('banana')
except vipsobject.VipsError, e:
print 'caught VipsError'
print '\tmessage =', e.message
print '\tdetail =', e.detail
# try calling a vips8 method
a = vipsimage.VipsImage('/home/john/pics/healthygirl.jpg')
b = vipsimage.VipsImage('/home/john/pics/babe.jpg')
c = a.add(b)
print 'c = ', c
c.write('/home/john/pics/x.v')
print 'starting shutdown ...'
del a
del b

View File

@ -9,6 +9,8 @@ GNU LESSER GENERAL PUBLIC LICENSE
import logging
import ctypes
import gobject
import vipsobject
# image enums
@ -45,7 +47,6 @@ class VipsInterpretation:
@staticmethod
def name(value):
print currentclass
return vipsobject.class_value(VipsInterpretation, value)
class VipsBandFormat:
@ -102,15 +103,14 @@ vips_image_get_xres.restype = ctypes.c_double;
vips_image_get_yres = libvips.vips_image_get_yres
vips_image_get_yres.restype = ctypes.c_double;
vips_operation_new = libvips.vips_operation_new
vips_operation_new.argtypes = [ctypes.c_char_p]
vips_operation_new.restype = ctypes.c_void_p
vips_operation_new.errcheck = vipsobject.check_pointer_return
def vips_call_instance(self, name, args):
logging.debug('vipsimage: vips_call_instance name=%s, self=%s, args=%s' %
(name, self, args))
operation = vipsoperation.VipsOperation(name)
operation = vips_operation_new(name)
vipsobject.vips_object_print(operation)
vipsobject.vips_argument_map(operation,
vipsobject.VipsArgumentMapFn(show_args),None, None)
class VipsImage(vipsobject.VipsObject):
"""Manipulate a libvips image."""

View File

@ -20,6 +20,26 @@ import finalizable
libvips = ctypes.CDLL('libvips.so.15')
libvips.vips_init(sys.argv[0])
vips_object_print = libvips.vips_object_print
vips_object_print.argtypes = [ctypes.c_void_p]
vips_object_print.restype = None
# in C:
# typedef void *(*VipsArgumentMapFn)( VipsObject *,
# GParamSpec *, VipsArgumentClass *, VipsArgumentInstance *,
# void *a, void *b );
VipsArgumentMapFn = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p)
vips_argument_map = libvips.vips_argument_map
vips_argument_map.argtypes = [ctypes.c_void_p, VipsArgumentMapFn,
ctypes.c_void_p, ctypes.c_void_p]
vips_argument_map.restype = ctypes.c_void_p
g_param_spec_get_name = libvips.g_param_spec_get_name
g_param_spec_get_name.argtypes = [ctypes.c_void_p]
g_param_spec_get_name.restype = ctypes.c_char_p
# given a class and value, search for a class member with that value
# handy for enum classes, use to turn numbers to strings
def class_value(classobject, value):
@ -45,7 +65,7 @@ class VipsError(Exception):
logging.debug('vipsobject: Error: %s %s', self.message, self.detail)
def __str__(self):
return '%s %s' %(self.message, self.detail)
return '%s %s' % (self.message, self.detail)
# handy checkers, assign to errcheck
def check_int_return(result, func, args):

46
python/vipsoperation.py Normal file
View File

@ -0,0 +1,46 @@
#!/usr/bin/python
"""This module wraps up libvips in a less awful interface.
Author: J.Cupitt
GNU LESSER GENERAL PUBLIC LICENSE
"""
import logging
import ctypes
import gobject
import vipsobject
libvips = vipsobject.libvips
vips_operation_new = libvips.vips_operation_new
vips_operation_new.argtypes = [ctypes.c_char_p]
vips_operation_new.restype = ctypes.c_void_p
vips_operation_new.errcheck = vipsobject.check_pointer_return
def show_args(operation, pspec, arg_class, arg_instance, a, b):
name = vipsobject.g_param_spec_get_name(pspec)
def vips_call_instance(self, name, args):
logging.debug('vipsimage: vips_call_instance name=%s, self=%s, args=%s' %
(name, self, args))
operation = vips_operation_new(name)
vipsobject.vips_object_print(operation)
vipsobject.vips_argument_map(operation,
vipsobject.VipsArgumentMapFn(show_args),None, None)
class VipsOperation(vipsobject.VipsObject):
"""Call a libvips operation."""
def __init__(self, name):
logging.debug('vipsoperation: init %s', name)
vipsobject.VipsObject.__init__(self)
self.vipsobject = vips_operation_new(name)
self.enable_finalize()
def call