Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

225 lines (195 sloc) 6.626 kb
xml2cython: process xml files generated by gccxml and generate cython code
xml2cython header xmlfile
By default, xml2cython pull out every function available in the xmlfile. There
are some basic filter you can use to limit the functions pulled out:
- -f/--filter-function-name: only pull out functions whose name match the
given string.
- -l/--location-filter: only pull out function which are declared in a file
whose name matches the given string.
xml2cython -f 'foo_' -l 'foo' header xmlfile
Will only pull out functions whose name match foo_ and which are declared
in file whose name match foo. Using regular expression instead of simple
strings should work"""
import getopt
import sys
import re
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
import cycodegenlib
from cycodegenlib.tp_puller import TypePuller
from cycodegenlib.misc import classify, query_items
from cycodegenlib.cycodegen import generate_cython
def generate_main(xml, output, lfilter=None, ffilter=None, funcs_list=None):
items, named, locations = query_items(xml)
funcs, tpdefs, enumvals, enums, structs, vars, unions, anoenums = \
classify(items, locations, lfilter=lfilter)
if ffilter is None:
ffilter = lambda x: True
if funcs_list:
kept_funcs = [i for i in funcs.values() if ffilter( \
and in funcs_list]
kept_funcs = [i for i in funcs.values() if ffilter(]
puller = TypePuller(items)
for f in kept_funcs:
needed = puller.values()
# Filter "anonymous" enumerations according to location
if lfilter:
anoenumvals = []
for v in anoenums.values():
anoenumvals = enumvals.values()
# Order 'anonymous' enum values alphabetically
def cmpenum(a, b):
return cmp(,
# List of items to generate code for
gen = list(needed) #+ kept_funcs
generate_cython(output, gen, anoenumvals)
class Usage(Exception):
def __init__(self, msg):
self.msg = """\
usage: xml2cython [options] headerfile xmlfile
%s""" % msg
def main(argv=None):
if argv is None:
argv = sys.argv
# parse command line options
opts, args = getopt.getopt(argv[1:], "ho:l:f:i:V",
["help", "output", "location-filter",
"input-file-filter", "--version"])
except getopt.error, msg:
raise Usage(msg)
except Usage, e:
print >>sys.stderr, e.msg
print >>sys.stderr, "for help use --help"
return 2
# process options
output = None
lfilter_str = None
ffilter_str = None
ifilter = None
for o, a in opts:
if o in ("-h", "--help"):
print __doc__
return 0
elif o in ("-o", "--output"):
output = a
elif o in ("-l", "--location-filter"):
lfilter_str = a
elif o in ("-f", "--function-name-filter"):
ffilter_str = a
elif o in ("-i", "--input-file-filter"):
ifilter = a
elif o in ("-V", "--version"):
print "xml2cython: use cycodegenlib version", cycodegenlib.version
return 0
if len(args) != 2:
print >>sys.stderr, "Error, exactly one input file must be specified"
print >>sys.stderr, "for help use --help"
return 2
header_input = args[0]
xml_input = args[1]
lfilter = None
if lfilter_str:
lfilter = re.compile(lfilter_str).search
ffilter = None
if ffilter_str:
ffilter = re.compile(ffilter_str).search
# Input file filter
funcs = []
if ifilter:
a = open(ifilter, 'r')
# Generate cython code
out = StringIO()
generate_main(xml_input, out, lfilter=lfilter,
ffilter=ffilter, funcs_list=funcs)
if output:
f = open(output, 'w')
f.write("# This file was generated by cycodegenlib, DO NOT EDIT\n")
f.write("# Generated by command %s\n" % " ".join(argv))
f.write("# Codegenlib version %s\n" % cycodegenlib.version)
f.write("cdef extern from '%s':\n" % header_input)
print out.getvalue()
if __name__ == '__main__':
# #root = 'asoundlib'
# #root = 'CoreAudio_AudioHardware'
# root = 'foo'
# header_name = '%s.h' % root
# #header_matcher = re.compile('alsa')
# header_matcher = re.compile(header_name)
# #header_matcher = re.compile('AudioHardware')
# xml_name = '%s.xml' % root
# pyx_name = '_%s.pyx' % root
# if sys.platform[:7] == 'darwin':
# so_name = root
# else:
# so_name = '' % root
# items, named, locations = query_items(xml_name)
# funcs, tpdefs, enumvals, enums, structs, vars, unions = \
# classify(items, locations,
# #arguments = signatures_types(funcs.values())
# #print "Need to pull out arguments", [named[i] for i in arguments]
# puller = TypePuller(items)
# for f in funcs.values():
# puller.pull(f)
# needed = puller.values()
# #print "Pulled out items:", [named[i] for i in needed]
# # Order 'anonymous' enum values alphabetically
# def cmpenum(a, b):
# return cmp(,
# anoenumvals = enumvals.values()
# anoenumvals.sort(cmpenum)
# # List of items to generate code for
# #gen = enumvals.values() + list(needed) + funcs.values()
# gen = list(needed) + funcs.values()
# #gen_names = [named[i] for i in gen]
# cython_code = [cy_generate(i) for i in gen]
# output = open(pyx_name, 'w')
# output.write("cdef extern from '%s':\n" % header_name)
# output.write("\tcdef enum:\n")
# for i in anoenumvals:
# output.write("\t\t%s = %d\n" % (, int(i.value)))
# for i in cython_code:
# if not i:
# continue
# if len(i) > 1:
# output.write("\t%s\n" % i[0])
# for j in i[1:]:
# output.write("\t%s\n" % j)
# else:
# output.write("\t%s\n" % i[0])
# output.close()
Jump to Line
Something went wrong with that request. Please try again.