如何使用libclang检索完全限定的函数名?

时间:2016-10-27 19:24:41

标签: python c++ libclang

我需要解析一个C ++代码文件,并使用完全限定名称查找其中的所有函数调用。我正在使用libclang的Python绑定,因为它似乎比编写我自己的C ++解析器更容易,即使文档很稀疏。

示例C ++代码:

namespace a {
  namespace b {
    class Thing {
    public:
      Thing();
      void DoSomething();
      int DoAnotherThing();
    private:
      int thisThing;
    };
  }
}

int main()
{
  a::b::Thing *thing = new a::b::Thing();
  thing->DoSomething();
  return 0;
}

Python脚本:

import clang.cindex
import sys

def find_function_calls(node):
  if node.kind == clang.cindex.CursorKind.CALL_EXPR:
    # What do I do here?
    pass
  for child in node.get_children():
    find_function_calls(child)

index = clang.cindex.Index.create()
tu = index.parse(sys.argv[1])
find_function_calls(tu.cursor)

我正在寻找的输出是一个被称为函数的完全限定名称列表:

a::b::Thing::Thing
a::b::Thing::DoSomething

我可以使用node.spelling来获取函数的“短”名称,但我不知道如何找到它所属的类/命名空间。

1 个答案:

答案 0 :(得分:3)

您可以使用游标public void checkEmpty() { String fname = jTextField1.getText(); String mname = jTextField2.getText(); String lname = jTextField3.getText(); String lineone = jTextField4.getText(); String linetwo = jTextField5.getText(); String linethree = jTextField6.getText(); int fnam = fname.length(); int mnam = mname.length(); int lnam = lname.length(); int lineon = lineone.length(); int linetw = linetwo.length(); int linethre = linethree.length(); int[] check = {fnam, mnam, lnam, lineon, linetw, linethre}; for (int i = 0; i < check.length; i++) { if (check[i] == 0) { } else { } } } 属性来获取定义的句柄,然后您可以通过referenced属性递归AST(在根处停止或当光标类型是翻译时) unit)建立完全限定的名称。

semantic_parent

产生:

import clang.cindex
from clang.cindex import CursorKind

def fully_qualified(c):
    if c is None:
        return ''
    elif c.kind == CursorKind.TRANSLATION_UNIT:
        return ''
    else:
        res = fully_qualified(c.semantic_parent)
        if res != '':
            return res + '::' + c.spelling
    return c.spelling

idx = clang.cindex.Index.create()
tu = idx.parse('tmp.cpp', args='-xc++ --std=c++11'.split())
for c in tu.cursor.walk_preorder():
    if c.kind == CursorKind.CALL_EXPR:
        print fully_qualified(c.referenced)