示例#1
0
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)
示例#2
0
 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
示例#3
0
    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)
示例#4
0
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
示例#5
0
    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
示例#6
0
    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
示例#7
0
#

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: