Пример #1
0
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
Пример #2
0
 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
Пример #3
0
 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
Пример #4
0
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)
Пример #5
0
    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)
Пример #6
0
 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)
Пример #7
0
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)
Пример #8
0
    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
Пример #9
0
 def setUp(self) -> None:
     # Create a clang parser instance, no flags
     self.parser = clangparser.Clang_Parser([])
Пример #10
0
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