def init(): conf = Config() # here we use the libclang.dylib from the vim plugin -- YouCompleteMe # path = "/Users/lono/.config/nvim/plugged/YouCompleteMe/third_party/ycmd" # path = "/Applications/Xcode.app/Contents/Frameworks" path = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib" # path = "/Library/Developer/CommandLineTools/usr/lib/" # path = "/Applications/Xcode8.app/Contents/Frameworks" Config.set_library_path(path) conf.set_library_path(path) try: conf.get_cindex_library() except LibclangError as e: print "Error: " + str(e)
def __init__(self, headName): index = clang.cindex.Index.create() self.Conf = Config() self.tu = index.parse(headName, args=['-std=c++11']) self.className = [] # class name stack self.classType = [] # class type stack: 'class','template','struct' self.headName = headName.split('/')[-1].split('.')[0] self.nameSpace = [] # namespace stack self.classDepth = 0 # the size of class stack self.waitPyx = '' # Nested class or struct or enum waiting to write to .pyx self.waitPxd = '' # Nested class or struct or enum waiting to write to .pxd self.typedefMap = {} # map a typedef name to its type self.constructCode = {} # map a class name to its constructors self.constructDict = { } # map a class name to the number of its constructor self.abstractMap = { } # map a class name to whether it is abstract or not self.construct = False # is now traversing constructor or not self.inClassEnum = False # is now traversing nested enum or not self.waitPxdChanged = False
def __init__(self, src, flags, input_stream, output_stream): self.src = src self.flags = flags self.input_stream = input_stream self.output_stream = output_stream self.index = Index.create() self.translation_unit = None self.completion_cache = None self.cached_contents = None conf = Config() self.custom_clang_lib = conf.lib self._register_custom_clang_functions() # Cache the libclang version. cxstr = self.custom_clang_lib.clang_getClangVersion() version = self.custom_clang_lib.clang_getCString(cxstr) if version.startswith(Server.CLANG_VERSION_PREFIX): version = version[len(Server.CLANG_VERSION_PREFIX):] else: version = '3.7.0' self.clang_version = LooseVersion(version)
def main(argv=None): """ Takes a set of C++ header files and generate a JSON output file describing the objects found in them. This output is intended to support more convenient access to a set of cppyy-supported bindings. Examples: INC=/usr/include QT5=$INC/x86_64-linux-gnu/qt5 KF5=$INC/KF5 INCDIRS="\\\\-I$KF5/KConfigCore;\\\\-I$QT5/QtXml;\\\\-I$QT5/QtCore" STDDIRS="\\\\-I$Qt5/mkspecs/linux-g++-64\\\\;-I$KF5;\\\\-I$QT5" FLAGS="\\\\-fvisibility=hidden;\\\-D__PIC__;\\\\-Wno-macro-redefined;\\\\-std=c++14" cppyy-generator --flags "$FLAGS;$INCDIRS;$STDDIRS" KF5/Config/Config.map $INC/KF5/KConfigCore/* """ if argv is None: argv = sys.argv parser = argparse.ArgumentParser(epilog=inspect.getdoc(main), formatter_class=HelpFormatter) parser.add_argument("-v", "--verbose", action="store_true", default=False, help=_("Enable verbose output")) parser.add_argument("--flags", default="", help=_("Semicolon-separated C++ compile flags to use, escape leading - or -- with \\")) parser.add_argument("--libclang", help=_("libclang library to use for parsing")) parser.add_argument("output", help=_("Output filename to write")) parser.add_argument("sources", nargs="+", help=_("C++ headers to process")) try: args = parser.parse_args(argv[1:]) if args.verbose: logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)s %(levelname)s: %(message)s') else: logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') flags = [] for f in args.flags.lstrip().split(";"): if f.startswith("\\-\\-"): flags.append("--" + f[4:]) elif f.startswith("\\-"): flags.append("-" + f[2:]) elif f: flags.append(f) # # Load the given libclang. # if args.libclang: Config.set_library_file(args.libclang) lib = Config().lib import ctypes from clang.cindex import Type items = [ ("clang_Type_getNumTemplateArguments", [Type], ctypes.c_size_t), ] for item in items: func = getattr(lib, item[0]) if len(item) >= 2: func.argtypes = item[1] if len(item) >= 3: func.restype = item[2] if len(item) == 4: func.errcheck = item[3] # # Generate! # g = CppyyGenerator(flags, verbose=args.verbose) mapping = g.create_mapping(args.sources) with open(args.output, "w") as f: json.dump(mapping, f, indent=1, sort_keys=True) return 0 except Exception as e: tbk = traceback.format_exc() print(tbk) return 1
def typedef_decl(self, container, typedef, level, h_file): """ Generate the translation for a typedef. :param container: A class or namespace. :param typedef: The typedef object. :param level: Recursion level controls indentation. :param h_file: The source header file of interest. :return: Info(). """ info = Info("typedef", typedef) template_count_stack = [] template_info_stack = [] template_stack_index = -1 parameters = None for child in typedef.get_children(): if child.kind in [CursorKind.STRUCT_DECL, CursorKind.UNION_DECL]: child_info = self._container_get(child, level, h_file) info["type"] = child_info elif child.kind == CursorKind.TEMPLATE_REF: # # Create an entry to collect information for this level of template arguments. # tmp = Config().lib.clang_Type_getNumTemplateArguments(typedef.type) if tmp == -1: logger.error(_("Unexpected template_arg_count={}").format(tmp)) # # Just a WAG... # tmp = 1 template_count_stack.append(tmp) template_info = Info("template", child) template_info["parameters"] = [] if template_stack_index == -1: template_info_stack.append(template_info) info["type"] = template_info else: # # Non-first template_infos are just parameters. # template_info_stack[template_stack_index]["parameters"].append(template_info) template_stack_index += 1 elif child.kind == CursorKind.TYPE_REF: if template_stack_index > -1: # # This is a template parameter. # template_parameters = template_info_stack[0]["parameters"] for i in range(template_stack_index): template_parameters = template_parameters[-1]["parameters"] template_parameters.append(child.spelling) template_count_stack[template_stack_index] -= 1 if template_count_stack[template_stack_index] == 0: template_stack_index -= 1 else: # # Not a template. # child_info = Info("type", child) info["type"] = child_info elif child.kind == CursorKind.PARM_DECL: # # This must be a function type. TODO: what if there are no PARM_DECLs? # if parameters is None: child_info = Info("function", typedef) info["type"] = child_info # # TODO: this is actually the signature: # # "int (Object::*)(QMetaObject::Call, int, void **)" # child_info["type"] = typedef.underlying_typedef_type.spelling parameters = [] child_info["parameters"] = parameters child_info = self._fn_get_parameter(typedef, child) parameters.append(child_info) else: CppyyGenerator._report_ignoring(child, "unusable") if "type" not in info: info["type"] = typedef.underlying_typedef_type.spelling parameters_fixup(level, info, "type") return info
def _container_get(self, container, level, h_file): """ Generate the (recursive) translation for a class or namespace. :param container: A class or namespace. :param level: Recursion level controls indentation. :param h_file: The source header file of interest. :return: Info(). """ def mark_forward_kinds(kind, definition): has_body = False # # Could this be a forward declaration? # for token in definition.get_tokens(): if token.kind == TokenKind.PUNCTUATION and token.spelling == "{": has_body = True if not has_body: kind = "forward " + kind return kind if container.kind == CursorKind.CLASS_DECL: kind = mark_forward_kinds("class", container) elif container.kind in [CursorKind.CLASS_TEMPLATE, CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION]: kind = mark_forward_kinds("template class", container) # # What level of template parameter is on this container? # container.template_level = 0 for parent in reversed(level): if parent.kind in [CursorKind.CLASS_TEMPLATE, CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION]: container.template_level = parent.template_level + 1 break container.template_params = [] elif container.kind == CursorKind.STRUCT_DECL: kind = mark_forward_kinds("struct", container) elif container.kind == CursorKind.UNION_DECL: kind = mark_forward_kinds("union", container) elif container.kind == CursorKind.NAMESPACE: kind = "namespace" elif container.kind == CursorKind.TRANSLATION_UNIT: kind = "file" else: logger.error(_("Unknown container kind {}").format(container.kind)) kind = container.kind info = Info(kind, container) children = [] info["children"] = children template_count_stack = [] template_info_stack = [] template_stack_index = -1 is_signal = False for child in container.get_children(): # # Only emit items in the translation unit. # if child.location.file.name != self.tu.spelling: continue if child.access_specifier == AccessSpecifier.PRIVATE: continue if child.kind in FN_KINDS: child_info = self._fn_get(container, child, level + [container], is_signal) children.append(child_info) elif child.kind == CursorKind.ENUM_DECL: child_info = self._enum_get(container, child, level.append(container)) children.append(child_info) elif child.kind == CursorKind.CXX_ACCESS_SPEC_DECL: is_signal = self._get_access_specifier(child) elif child.kind == CursorKind.TYPEDEF_DECL: child_info = self.typedef_decl(container, child, level + [container], h_file) # # Structs and unions are emitted twice: # # - first as just the bare fields # - then as children of the typedef # if "type" in child_info and child_info["type"]["kind"] in ("struct", "union"): assert children[-1] == child_info["type"] children.pop() children.append(child_info) elif child.kind in [CursorKind.NAMESPACE, CursorKind.CLASS_DECL, CursorKind.CLASS_TEMPLATE, CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, CursorKind.STRUCT_DECL, CursorKind.UNION_DECL]: child_info = self._container_get(child, level + [container], h_file) children.append(child_info) elif child.kind in [CursorKind.FIELD_DECL]: child_info = self._var_get("field", child, level + [container]) children.append(child_info) elif child.kind in [CursorKind.VAR_DECL]: child_info = self._var_get("variable", child, level + [container]) children.append(child_info) elif child.kind in [CursorKind.TEMPLATE_TYPE_PARAMETER, CursorKind.TEMPLATE_NON_TYPE_PARAMETER, CursorKind.TEMPLATE_TEMPLATE_PARAMETER]: info["parameters"] = container.template_params param_info = Info("parameter", child) container.template_params.append(param_info) elif child.kind == CursorKind.TEMPLATE_REF: # # Create an entry to collect information for this level of template arguments. # tmp = Config().lib.clang_Type_getNumTemplateArguments(container.type) template_count_stack.append(tmp) template_info = Info("template", child) template_info["parameters"] = [] if template_stack_index == -1: template_info_stack.append(template_info) info["type"] = template_info else: # # Non-first template_infos are just parameters. # template_info_stack[template_stack_index]["parameters"].append(template_info) template_stack_index += 1 elif child.kind == CursorKind.TYPE_REF: if template_stack_index > -1: # # This is a template parameter. # template_parameters = template_info_stack[0]["parameters"] for i in range(template_stack_index): template_parameters = template_parameters[-1]["parameters"] template_parameters.append(child.spelling) template_count_stack[template_stack_index] -= 1 if template_count_stack[template_stack_index] == 0: template_stack_index -= 1 else: # # Not a template. # child_info = Info("type", child) info["type"] = child_info else: CppyyGenerator._report_ignoring(child, "unusable") if self.dump_items: logger.info(_("Processing {}").format(item_describe(child))) return info
# from cppyy_backend._cppyy_generator import CppyyGenerator from clang.cindex import Config from pprint import pprint import glob import os.path proj_dir = '../../PySysC-SC/components' flags = [ '-I/home/eyck/.conan/data/SystemC/2.3.2/minres/stable/package/672f3350f4be793d25afa19a6a77085e20d01ea5/include', '-I' + proj_dir, '-fvisibility=hidden', '-D__PIC__', '-Wno-macro-redefined', '-std=c++11' ] Config.set_library_file('/usr/lib/x86_64-linux-gnu/libclang-6.0.so') lib = Config().lib import ctypes from clang.cindex import Type items = [ ("clang_Type_getNumTemplateArguments", [Type], ctypes.c_size_t), ] for item in items: func = getattr(lib, item[0]) if len(item) >= 2: func.argtypes = item[1] if len(item) >= 3: func.restype = item[2] if len(item) == 4: