使用libclang时,如何从stdio.h中排除函数?
当我使用下面的源只收集函数定义时,我最终也从stdio.h获取所有函数。
我读过我们可以在创建索引时传递'-x c-header'类型的参数。但这种方式是否适用于libclang。
tu = index.parse(self.filename, "-x c-header")
在包含'c-header'参数后,它还要我填写'unsaved_files'数组,根据'cindex.py'中'解析'函数的定义。
def parse(self, path, args = [], unsaved_files = [], options = 0):
我不知道这样做的正确方法是什么。
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)
答案 0 :(得分:1)
-x c-header
命令行开关用于生成precompiled headers,而不是从翻译单元中排除标题。
我认为从特定文件中排除函数的正确方法是在访问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
的python API)的专家,但我认为你的例子遵循C API概念而不是python概念。引用文档(强调我的):
此模块提供Clang索引库的接口。它是一个 索引库的低级接口,它尝试匹配Clang API直接同时也是“pythonic”。与C API有显着差异 是:
字符串结果以Python字符串形式返回,而不是CXString对象。
null游标已转换为None。
访问子游标是通过迭代而不是访问来完成的。
虽然cindex.py
将Cursor_visit
绑定到clang_visitChildren
,但它甚至不会导出CXChildVisitResult
枚举,这意味着您需要对Break
的值进行硬编码, Continue
和Recurse
。 pythonic的做事方式包括迭代子节点,由Cursor.get_children()
方法返回。这些SO答案(1,2)中给出了一个示例,您可以根据源文件过滤掉节点。