def gen_python_bindings(outdir, path): import ctypeslib from ctypeslib.codegen import clangparser from ctypeslib.codegen import codegenerator pyout = StringIO() fname = os.path.splitext(os.path.basename(path))[0] print(get_compiler_include_paths()) # TODO: Make it configurable clang_opts = r2_includes + c_includes parser = clangparser.Clang_Parser(flags=clang_opts) print("Parsing {0:s} file...\n".format(path)) items = parser.parse(path) if items is None: print("Error parsing {0} file!\n".format(fname)) return False gen = codegenerator.Generator(pyout) # See ctypeslib/clang2py.py for more options gen.generate(parser, items, flags=[], verbose=True) outfname = outdir + "/" + fname + ".py" with fopen(outfname, "w") as f: f.write(pyout.getvalue()) pyout.close() return True pyout.close() print("Cannot write {0}.py file!\n".format(fname)) return False
def _gen(self, ofi, fname, flags=[]): """Take a file input and generate the code. """ # leave the new parser accessible for tests self.parser = clangparser.Clang_Parser(flags) if self.full_parsing_options: self.parser.activate_macros_parsing() self.parser.activate_comment_parsing() with open(fname): pass self.parser.parse(fname) items = self.parser.get_result() # gen code gen = codegenerator.Generator(ofi) gen.generate_headers(self.parser) gen.generate_code(items) return gen
def _gen(self, ofi, fname, flags=None, dlls=None): """Take a file input and generate the code. """ flags = flags or [] dlls = [Library(name, nm="nm") for name in dlls] # leave the new parser accessible for tests self.parser = clangparser.Clang_Parser(flags) if self.full_parsing_options: self.parser.activate_macros_parsing() self.parser.activate_comment_parsing() with open(fname): pass self.parser.parse(fname) items = self.parser.get_result() # gen code cross_arch = '-target' in ' '.join(flags) gen = codegenerator.Generator(ofi, searched_dlls=dlls, cross_arch=cross_arch) gen.generate_headers(self.parser) gen.generate_code(items) return gen
def run(): parser = clangparser.Clang_Parser(('-I/usr/include/clang/5.0/include/', )) parser.filter_location([ os.path.abspath('pynfc/nfc.c'), os.path.abspath('pynfc/freefare.c'), os.path.abspath('pynfc/mifare.c'), '/usr/include/freefare.h', '/usr/include/nfc/nfc-types.h', '/usr/include/nfc/nfc.h', ]) parser.parse(os.path.abspath('pynfc/nfc.c')) items = parser.get_result() items = [ i for i in items if isinstance(i, (typedesc.Function, typedesc.Typedef)) ] with open('pynfc/nfc.py', 'w') as out: gen = MyGenerator(out, searched_dlls=(ctypes.CDLL('libfreefare.so'), )) gen.generate_headers(parser) gen.generate_code(items)
def run(self): """Use ctypelib2 to convert to python.""" from ctypeslib.codegen import clangparser, config from ctypeslib.codegen.codegenerator import Generator from ctypeslib.library import Library parser = clangparser.Clang_Parser(()) parser.parse("pynfc/nfc.c") items = parser.get_result() conf = config.CodegenConfig() conf.searched_dlls = ( Library("/usr/lib/x86_64-linux-gnu/libnfc.so", "nm"), Library("/usr/lib/x86_64-linux-gnu/libfreefare.so", "nm"), ) with open("pynfc/nfc.py", "w") as out: gen = Generator(out, conf) gen.generate_headers(parser) gen.generate_code(items) return build_py.run(self)
def gen(self, fname, flags=[]): """Take a file input and generate the code. """ ofi = StringIO() # leave the new parser accessible for tests self.parser = clangparser.Clang_Parser(flags) with open(fname): pass self.parser.parse(fname) items = self.parser.get_result() # gen code gen = codegenerator.Generator(ofi) gen.generate_headers(self.parser) gen.generate_code(items) # load code namespace = {} # DEBUG #print ofi.getvalue() # DEBUG exec ofi.getvalue() in namespace return ADict(namespace)
def generate_code(srcfiles, outfile, expressions=None, symbols=None, verbose=False, generate_comments=False, known_symbols=None, searched_dlls=None, types=None, preloaded_dlls=None, generate_docstrings=False, generate_locations=False, filter_location=False, flags=None): # expressions is a sequence of compiled regular expressions, # symbols is a sequence of names parser = clangparser.Clang_Parser(flags or []) # if macros are not needed, use a faster TranslationUnit if typedesc.Macro in types: parser.activate_macros_parsing() if generate_comments is True: parser.activate_comment_parsing() if filter_location is True: parser.filter_location(srcfiles) # items = [] for srcfile in srcfiles: # verifying that is really a file we can open with open(srcfile): pass parser.parse(srcfile) items += parser.get_result() log.debug('Input was parsed') # filter symbols to generate todo = [] if types: items = [i for i in items if isinstance(i, types)] if symbols: syms = set(symbols) for i in items: if i.name in syms: todo.append(i) syms.remove(i.name) if syms: log.warning("symbols not found %s", [str(x) for x in list(syms)]) if expressions: for s in expressions: log.debug("regexp: looking for %s", s.pattern) for i in items: log.debug("regexp: i.name is %s", i.name) if i.name is None: continue match = s.match(i.name) # if we only want complete matches: if match and match.group() == i.name: todo.append(i) break # if we follow our own documentation, # allow regular expression match of any part of name: match = s.search(i.name) if match: todo.append(i) break if symbols or expressions: items = todo ################ gen = Generator(outfile, generate_locations=generate_locations, generate_comments=generate_comments, generate_docstrings=generate_docstrings, known_symbols=known_symbols, searched_dlls=searched_dlls, preloaded_dlls=preloaded_dlls) # add some headers and ctypes import gen.generate_headers(parser) # make the structures loops = gen.generate_code(items) if verbose: gen.print_stats(sys.stderr) print("needed %d loop(s)" % loops, file=sys.stderr)
def test_example(self): """Test ctypeslib inline in a python script""" flags = ['-target', 'i386-linux'] source_code = """ struct example_detail { int first; int last; }; struct example { int argsz; int flags; int count; struct example_detail details[2]; }; """ # Create a clang parser instance, with the clang target flags self.parser = clangparser.Clang_Parser(flags) if self.full_parsing_options: self.parser.activate_macros_parsing() self.parser.activate_comment_parsing() try: # we have to store the code in a physical file. # libclang does not work on memory buffers. handle, filename = tempfile.mkstemp(".h") open(filename, "w").write(source_code) # race condition self.parser.parse(filename) items = self.parser.get_result() finally: os.unlink(filename) # use ctypeslib to generate Python ctypes code ofi = StringIO() # Create a ctypeslib code generator gen = codegenerator.Generator(ofi) # generate the code, first some headers and ctypes import gen.generate_headers(self.parser) # then the actual python structures gen.generate_code(items) # Now we can load code in a virtual module namespace namespace = {} # rewind the String Buffer ofi.seek(0) # ignore the first line to remove error # "SyntaxError: encoding declaration in Unicode string" ignore_coding = ofi.readline() # read the whole python code output = ''.join(ofi.readlines()) # load the code in a module example = ModuleType('example') try: # run the python code in a namespace exec(output, example.__dict__) except ValueError: print(output) # print the python code. #print(output) # use the module one = example.struct_example() #print("Allocating struct detail one: %s" % type(one)) one.count = 1 one.details[0].first = 12 assert (one.count == 1) assert (one.details[0].first == 12) #print("Sizeof structure one: %d" % ctypes.sizeof(one)) #print("\tone.count == %d" % one.count) #print("\tone.details[0].first == %d" % one.details[0].first) return
def setUp(self) -> None: # Create a clang parser instance, no flags self.parser = clangparser.Clang_Parser([])
def generate_code(srcfiles, outfile, expressions=None, symbols=None, verbose=False, generate_comments=False, known_symbols=None, searched_dlls=None, types=None, preloaded_dlls=[], generate_docstrings=False, generate_locations=False, generate_includes=False, filter_location=True, flags=[] ): # expressions is a sequence of compiled regular expressions, # symbols is a sequence of names parser = clangparser.Clang_Parser(flags) # if macros are not needed, use a faster TranslationUnit if typedesc.Macro in types: parser.activate_macros_parsing() if generate_comments is True: parser.activate_comment_parsing() if filter_location is True: parser.filter_location(srcfiles) # items = [] for srcfile in srcfiles: with open(srcfile): pass parser.parse(srcfile) items += parser.get_result() log.debug('Input was parsed') #code.interact(local=locals()) # filter symbols to generate todo = [] if types: items = [i for i in items if isinstance(i, types)] if not generate_includes: # limit generation to definitions in srcfiles only items = [i for i in items if i.location[0] in srcfiles] if symbols: syms = set(symbols) for i in items: if i.name in syms: todo.append(i) syms.remove(i.name) if syms: log.warning( "symbols not found %s"%( [str(x) for x in list(syms)])) if expressions: for i in items: for s in expressions: if i.name is None: continue match = s.match(i.name) # we only want complete matches if match and match.group() == i.name: todo.append(i) break if symbols or expressions: items = todo ################ gen = Generator(outfile, generate_locations=generate_locations, generate_comments=generate_comments, generate_docstrings=generate_docstrings, known_symbols=known_symbols, searched_dlls=searched_dlls, preloaded_dlls=preloaded_dlls) # add some headers and ctypes import gen.generate_headers(parser) # make the structures loops = gen.generate_code(items) if verbose: gen.print_stats(sys.stderr) print >> sys.stderr, "needed %d loop(s)" % loops