1

When using libclang, how to exclude function from stdio.h ?

When I use the below source to collect only function definitions, then I end up getting all the functions from stdio.h as well.

I read we can pass '-x c-header' kind of arguments while creating index. But does this way of giving arguments applicable in libclang.

tu = index.parse(self.filename, "-x c-header")

After including 'c-header' argument, it wants me to fill in 'unsaved_files' array as well, as per the definition of 'parse' function in 'cindex.py'.

def parse(self, path, args = [], unsaved_files = [], options = 0):

I don't know what is the right way to do this.

def funcdefn_visitor(self, node, parent, userdata):
    if node.kind == clang.cindex.CursorKind.FUNCTION_DECL: #gives function definitions
        self.func_defn.append(clang.cindex.Cursor_displayname(node))
        self.func_defn_line_no.append(node.location.line)
        self.func_defn_col_no.append(node.location.column)
    print 'Found %s [line=%s, col=%s]' % (
        clang.cindex.Cursor_displayname(node),
        node.location.line,
        node.location.column)
    return 2 # means continue visiting recursively

index = clang.cindex.Index.create()

tu = index.parse(self.filename)
#-- link cursor visitor to call back to give function definitions
clang.cindex.Cursor_visit(
    tu.cursor,
    clang.cindex.Cursor_visit_callback(self.funcdefn_visitor),
    None)
4

1 回答 1

1

-x c-header命令行开关用于生成预编译的标头,而不是从翻译单元中排除标头。

我认为从特定文件中排除函数的正确方法是在访问 AST 时跳过位于其中的所有节点。为了详细说明您的示例,这个想法是在访问者中进行第一次测试,以尽早跳过文件并避免访问其所有子节点。

def funcdefn_visitor(self, node, parent, userdata):

    # You might want to change the test here
    if node.location.file.endswith("/stdio.h"):
        print "Skipping 'stdio.h'"
        # Continue with next sibling
        return 1

    if node.kind == clang.cindex.CursorKind.FUNCTION_DECL: #gives function definitions
        self.func_defn.append(clang.cindex.Cursor_displayname(node))
        self.func_defn_line_no.append(node.location.line)
        self.func_defn_col_no.append(node.location.column)

    print 'Found %s [line=%s, col=%s]' % (
        clang.cindex.Cursor_displayname(node),
        node.location.line,
        node.location.column)

    # Continue visiting recursively
    return 2

index = clang.cindex.Index.create()

tu = index.parse(self.filename)
#-- link cursor visitor to call back to give function definitions
clang.cindex.Cursor_visit(
    tu.cursor,
    clang.cindex.Cursor_visit_callback(self.funcdefn_visitor),
    None)

现在我不是cindex.py( libclang's python API) 的专家,但我认为您的示例遵循 C API 概念而不是 python 概念。引用文档(强调我的):

该模块提供了 Clang 索引库的接口。它是索引库的低级接口,它尝试直接匹配 Clang API,同时也是“pythonic”。与 C API 的显着区别是:

  • 字符串结果作为 Python 字符串返回,而不是 CXString 对象。

  • 空游标被转换为无。

  • 对子游标的访问是通过迭代完成的,而不是访问。

虽然cindex.py绑定Cursor_visitclang_visitChildren,但它甚至不导出CXChildVisitResult枚举,这意味着您需要硬编码和Break的值。pythonic 的做事方式包括在子节点上迭代,由方法返回。这些 SO 答案 ( 1 , 2 )中给出了一个示例,您可以根据源文件对其进行调整以过滤掉节点。ContinueRecurseCursor.get_children()

于 2014-01-31T08:36:11.217 回答