import os import json from clang.cindex import Index, CursorKind def load_compile_flags(compile_commands_path, cpp_stub_path): with open(compile_commands_path) as f: compile_commands = json.load(f) for entry in compile_commands: if os.path.abspath(entry['file']) == os.path.abspath(cpp_stub_path): cmd = entry['arguments'] if 'arguments' in entry else entry['command'].split() if "-c" in cmd: del cmd[cmd.index("-c") + 1] del cmd[cmd.index("-c")] return [arg for arg in cmd if not arg.endswith('g++') and not arg.endswith('clang++')] return [] def has_annotation(cursor, annotation_text): return any( c.kind == CursorKind.ANNOTATE_ATTR and annotation_text in c.spelling for c in cursor.get_children() ) def main(): cpp_stub_path = os.path.abspath("src/ICounter.cpp") compile_commands_path = os.path.abspath("build/compile_commands.json") args = load_compile_flags(compile_commands_path, cpp_stub_path) print(args) index = Index.create() tu = index.parse(cpp_stub_path, args=args, options=0) for cursor in tu.cursor.walk_preorder(): if cursor.kind == CursorKind.CLASS_DECL and has_annotation(cursor, "export"): print(f"Found exported class: {cursor.spelling}") for c in cursor.get_children(): if c.kind == CursorKind.CXX_METHOD and has_annotation(c, "export"): is_virtual = c.is_virtual_method() print(f" method: {c.spelling} (virtual={is_virtual})") if __name__ == "__main__": main()