[vlc-commits] Implement callbacks wrapping
Olivier Aubert
git at videolan.org
Thu Jun 14 15:27:18 CEST 2012
vlc/python | branch: master | Olivier Aubert <olivier.aubert at liris.cnrs.fr> | Sat Jun 9 00:31:53 2012 +0200| [46713f9ab53e3cdb4e71a37f13595ee437aa2ac2] | committer: Olivier Aubert
Implement callbacks wrapping
Define decorators to wrap callback methods that can be called from libvlc.
> http://git.videolan.org/gitweb.cgi/vlc/python.git/?a=commit;h=46713f9ab53e3cdb4e71a37f13595ee437aa2ac2
---
generate.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 70 insertions(+), 11 deletions(-)
diff --git a/generate.py b/generate.py
index ae08a99..a4db830 100755
--- a/generate.py
+++ b/generate.py
@@ -71,14 +71,8 @@ else: # Python 3+
# Functions not wrapped/not referenced
_blacklist = {
- 'libvlc_set_exit_handler': '', # not in 1.1.5?
+ 'libvlc_set_exit_handler': '',
'libvlc_video_set_callbacks': '',
- 'libvlc_video_set_format_callbacks': '',
- 'libvlc_audio_set_callbacks': '',
- 'libvlc_audio_set_format_callbacks': '',
- 'libvlc_audio_set_volume_callback': '',
- 'libvlc_vprinterr': '',
- 'libvlc_printerr': '',
}
# Set of functions that return a string that the caller is
@@ -116,9 +110,11 @@ at_param_re = re.compile('(@param\s+\S+)(.+)')
bs_param_re = re.compile('\\param\s+(\S+)')
class_re = re.compile('class\s+(\S+):')
def_re = re.compile('^\s+def\s+(\w+)', re.MULTILINE)
+enum_type_re = re.compile('^(?:typedef\s+)?enum')
enum_re = re.compile('(?:typedef\s+)?(enum)\s*(\S+)\s*\{\s*(.+)\s*\}\s*(?:\S+)?;')
enum_pair_re = re.compile('\s*=\s*')
-enum_type_re = re.compile('^(?:typedef\s+)?enum')
+callback_type_re = re.compile('^typedef\s+\w+(\s+\*)?\s+\(\s*\*')
+callback_re = re.compile('typedef\s+(\w+\s*\*?)\s*\(\s*\*\s*(\w+)\s*\)\s*\((.+)\);')
forward_re = re.compile('.+\(\s*(.+?)\s*\)(\s*\S+)')
libvlc_re = re.compile('\slibvlc_[a-z_]+')
param_re = re.compile('\s*(const\s*|unsigned\s*|struct\s*)?(\S+\s*\**)\s+(.+)')
@@ -370,6 +366,7 @@ class Parser(object):
def __init__(self, h_files, version=''):
self.enums = []
+ self.callbacks = []
self.funcs = []
self.version = version
@@ -381,6 +378,7 @@ class Parser(object):
break
self.h_file = h
self.enums.extend(self.parse_enums())
+ self.callbacks.extend(self.parse_callbacks())
self.funcs.extend(self.parse_funcs())
def check(self):
@@ -390,13 +388,25 @@ class Parser(object):
e.check()
for f in self.funcs:
f.check()
+ for f in self.callbacks:
+ f.check()
def dump(self, attr):
sys.stderr.write('%s==== %s ==== %s\n' % (_NL_, attr, self.version))
for a in getattr(self, attr, ()):
a.dump()
+ def parse_callbacks(self):
+ """Parse header file for callback signature definitions.
+
+ @return: yield a Func instance for each callback signature, unless blacklisted.
+ """
+ for type_, name, pars, docs, line in self.parse_groups(callback_type_re.match, callback_re.match, ');'):
+
+ pars = [self.parse_param(p) for p in paramlist_re.split(pars)]
+ yield Func(name, type_.replace(' ', '') + '*', pars, docs,
+ file_=self.h_file, line=line)
def parse_enums(self):
"""Parse header file for enum type definitions.
@@ -558,6 +568,7 @@ class _Generator(object):
##self.type2class = self.type2class.copy()
self.parser = parser
self.convert_enums()
+ self.convert_callbacks()
def check_types(self):
"""Make sure that all types are properly translated.
@@ -593,6 +604,17 @@ class _Generator(object):
c = c.capitalize()
self.type2class[e.name] = c
+ def convert_callbacks(self):
+ """Convert callback names to class names.
+ """
+ for f in self.parser.callbacks:
+ c = self.type_re.findall(f.name)[0][0]
+ if '_' in c:
+ c = c.title().replace('_', '')
+ elif c[0].islower():
+ c = c.capitalize()
+ self.type2class[f.name] = c
+
def dump_dicts(self): # for debug
s = _NL_ + _INDENT_
for n in ('type2class', 'prefixes', 'links'):
@@ -629,6 +651,7 @@ class _Generator(object):
for t in f:
if genums and t.startswith(_GENERATED_ENUMS_):
self.generate_enums()
+ self.generate_callbacks()
elif t.startswith(_BUILD_DATE_):
v, t = _NA_, self.parser.version
if t:
@@ -691,7 +714,8 @@ class PythonGenerator(_Generator):
# type conversions are generated (cf convert_enums).
type2class = {
'libvlc_audio_output_t*': 'ctypes.POINTER(AudioOutput)',
- 'libvlc_callback_t': 'ctypes.c_void_p',
+ 'libvlc_event_t*': 'ctypes.c_void_p',
+ #'libvlc_callback_t': 'ctypes.c_void_p',
'libvlc_drawable_t': 'ctypes.c_uint', # FIXME?
'libvlc_event_type_t': 'ctypes.c_uint',
'libvlc_event_manager_t*': 'EventManager',
@@ -715,9 +739,10 @@ class PythonGenerator(_Generator):
'libvlc_module_description_t*': 'ctypes.POINTER(ModuleDescription)',
'FILE*': 'FILE_ptr',
- '...': 'FIXME_va_list',
- 'va_list': 'FIXME_va_list',
+ '...': 'ctypes.c_void_p',
+ 'va_list': 'ctypes.c_void_p',
'char*': 'ctypes.c_char_p',
+ 'bool': 'ctypes.c_bool',
'char**': 'ListPOINTER(ctypes.c_char_p)',
'float': 'ctypes.c_float',
'int': 'ctypes.c_int',
@@ -878,6 +903,40 @@ class _Enum(ctypes.c_uint):
self.output(_NL_.join(sorted(t)), nt=2)
+ def generate_callbacks(self):
+ """Generate decorators for callback functions.
+
+ We generate both decorators (for defining functions) and
+ associated classes, to help in defining function signatures.
+ """
+ if not self.parser.callbacks:
+ return
+ # Generate classes
+ for f in self.parser.callbacks:
+ name = self.class4(f.name) #PYCHOK flake
+ docs = self.epylink(f.docs)
+ self.output('''class %(name)s(ctypes.c_void_p):
+ """%(docs)s
+ """
+ pass''' % locals())
+
+ self.output("class CallbackDecorators(object):")
+ self.output(' "Class holding various method decorators for callback functions."')
+ for f in self.parser.callbacks:
+ name = self.class4(f.name) #PYCHOK flake
+
+ # return value and arg classes
+ types = ', '.join([self.class4(f.type)] + #PYCHOK flake
+ [self.class4(p.type) for p in f.pars])
+
+ # xformed doc string with first @param
+ docs = self.epylink(f.docs)
+
+ self.output(""" %(name)s = ctypes.CFUNCTYPE(%(types)s)
+ %(name)s.__doc__ = '''%(docs)s
+ ''' """ % locals())
+ self.output("cb = CallbackDecorators")
+
def generate_wrappers(self):
"""Generate class wrappers for all appropriate functions.
"""
More information about the vlc-commits
mailing list