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 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 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