forked from ctypesgen/ctypesgen
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ctypesgen.py
executable file
·170 lines (148 loc) · 7.61 KB
/
ctypesgen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python
# -*- coding: us-ascii -*-
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
def find_names_in_modules(modules):
names = set()
for module in modules:
try:
mod = __import__(module)
except:
pass
else:
names.union(dir(module))
return names
import optparse, sys
def option_callback_W(option, opt, value, parser):
# Options preceded by a "-Wl," are simply treated as though the "-Wl,"
# is not there? I don't understand the purpose of this code...
if len(value) < 4 or value[0:3] != 'l,-':
raise optparse.BadOptionError("not in '-Wl,<opt>' form: %s%s"
% (opt, value))
opt = value[2:]
if opt not in ['-L', '-R', '--rpath']:
raise optparse.BadOptionError("-Wl option must be -L, -R"
" or --rpath, not " + value[2:])
# Push the linker option onto the list for further parsing.
parser.rargs.insert(0, value)
def option_callback_libdir(option, opt, value, parser):
# There are two sets of linker search paths: those for use at compile time
# and those for use at runtime. Search paths specified with -L, -R, or
# --rpath are added to both sets.
parser.values.compile_libdirs.append(value)
parser.values.runtime_libdirs.append(value)
import ctypesgencore
import ctypesgencore.messages as msgs
if __name__=="__main__":
usage = 'usage: %prog [options] /path/to/header.h ...'
op = optparse.OptionParser(usage=usage)
# Parameters
op.add_option('-o', '--output', dest='output', metavar='FILE',
help='write wrapper to FILE [default stdout]')
op.add_option('-l', '--library', dest='libraries', action='append',
default=[], metavar='LIBRARY', help='link to LIBRARY')
op.add_option('', '--include', dest='other_headers', action='append',
default=[], metavar='HEADER',
help='include system header HEADER (e.g. stdio.h or stdlib.h)')
op.add_option('-m', '--module', '--link-module', action='append',
dest='modules', metavar='MODULE', default=[],
help='use symbols from Python module MODULE')
op.add_option('-I', '--includedir', dest='include_search_paths',
action='append', default=[], metavar='INCLUDEDIR',
help='add INCLUDEDIR as a directory to search for headers')
op.add_option('-W', action="callback", callback=option_callback_W,
metavar="l,OPTION", type="str",
help="where OPTION is -L, -R, or --rpath")
op.add_option("-L", "-R", "--rpath", "--libdir", action="callback",
callback=option_callback_libdir, metavar="LIBDIR", type="str",
help="Add LIBDIR to the search path (both compile-time and run-time)")
op.add_option('', "--compile-libdir", action="append",
dest="compile_libdirs", metavar="LIBDIR", default=[],
help="Add LIBDIR to the compile-time library search path.")
op.add_option('', "--runtime-libdir", action="append",
dest="runtime_libdirs", metavar="LIBDIR", default=[],
help="Add LIBDIR to the run-time library search path.")
# Parser options
op.add_option('', '--cpp', dest='cpp', default='gcc -E',
help='The command to invoke the c preprocessor, including any ' \
'necessary options (default: gcc -E)')
op.add_option('', '--save-preprocessed-headers', metavar='FILENAME',
dest='save_preprocessed_headers', default=None,
help='Save the preprocessed headers to the specified FILENAME')
# Processor options
op.add_option('-a', '--all-headers', action='store_true',
dest='all_headers', default=False,
help='include symbols from all headers, including system headers')
op.add_option('', '--builtin-symbols', action='store_true',
dest='builtin_symbols', default=False,
help='include symbols automatically generated by the preprocessor')
op.add_option('', '--no-macros', action='store_false', dest='include_macros',
default=True, help="Don't output macros.")
op.add_option('-i', '--include-symbols', dest='include_symbols',
default=None, help='regular expression for symbols to always include')
op.add_option('-x', '--exclude-symbols', dest='exclude_symbols',
default=None, help='regular expression for symbols to exclude')
op.add_option('', '--no-stddef-types', action='store_true',
dest='no_stddef_types', default=False,
help='Do not support extra C types from stddef.h')
op.add_option('', '--no-gnu-types', action='store_true',
dest='no_gnu_types', default=False,
help='Do not support extra GNU C types')
op.add_option('', '--no-python-types', action='store_true',
dest='no_python_types', default=False,
help='Do not support extra C types built in to Python')
# Printer options
op.add_option('', '--header-template', dest='header_template', default=None,
metavar='TEMPLATE',
help='Use TEMPLATE as the header template in the output file.')
op.add_option('', '--strip-build-path', dest='strip_build_path',
default=None, metavar='BUILD_PATH',
help='Strip build path from header paths in the wrapper file.')
op.add_option('', '--insert-file', dest='inserted_files', default=[],
action='append', metavar='FILENAME',
help='Add the contents of FILENAME to the end of the wrapper file.')
op.add_option('', '--output-language', dest='output_language', metavar='LANGUAGE',
default='python',
help="Choose output language (`json' or `python' [default])")
# Error options
op.add_option('', "--all-errors", action="store_true", default=False,
dest="show_all_errors", help="Display all warnings and errors even " \
"if they would not affect output.")
op.add_option('', "--show-long-errors", action="store_true", default=False,
dest="show_long_errors", help="Display long error messages " \
"instead of abbreviating error messages.")
op.add_option('', "--no-macro-warnings", action="store_false", default=True,
dest="show_macro_warnings", help="Do not print macro warnings.")
op.set_defaults(**ctypesgencore.options.default_values)
(options, args) = op.parse_args(list(sys.argv[1:]))
options.headers = args
# Figure out what names will be defined by imported Python modules
options.other_known_names = find_names_in_modules(options.modules)
# Required parameters
if len(args) < 1:
msgs.error_message('No header files specified', cls='usage')
sys.exit(1)
if len(options.libraries) == 0:
msgs.warning_message('No libraries specified', cls='usage')
# Check output language
printer = None
if options.output_language == "python":
printer = ctypesgencore.printer_python.WrapperPrinter
elif options.output_language == "json":
printer = ctypesgencore.printer_json.WrapperPrinter
else:
msgs.error_message("No such output language `" + options.output_language + "'", cls='usage')
sys.exit(1)
# Step 1: Parse
descriptions=ctypesgencore.parser.parse(options.headers,options)
# Step 2: Process
ctypesgencore.processor.process(descriptions,options)
# Step 3: Print
printer(options.output,options,descriptions)
msgs.status_message("Wrapping complete.")
# Correct what may be a common mistake
if descriptions.all == []:
if not options.all_headers:
msgs.warning_message("There wasn't anything of use in the " \
"specified header file(s). Perhaps you meant to run with " \
"--all-headers to include objects from included sub-headers? ",
cls = 'usage')