python.clangast解析:获取c++;字段声明的模板参数

python.clangast解析:获取c++;字段声明的模板参数,python,c++,templates,clang,abstract-syntax-tree,Python,C++,Templates,Clang,Abstract Syntax Tree,我正在使用clang通过python接口提供的抽象语法树,试图解析包含std::vector的简单结构: #include <vector> struct outer_t { std::vector<int> vec_of_ints; }; 这将产生以下结果: node.spelling = vec_of_ints , node.kind = CursorKind.FIELD_DECL node.spelling = std , nod

我正在使用clang通过python接口提供的抽象语法树,试图解析包含std::vector的简单结构:

#include <vector>

struct outer_t
{
    std::vector<int> vec_of_ints;
};
这将产生以下结果:

node.spelling = vec_of_ints   , node.kind = CursorKind.FIELD_DECL
node.spelling = std           , node.kind = CursorKind.NAMESPACE_REF
node.spelling = vector        , node.kind = CursorKind.TEMPLATE_REF
node.get_num_template_arguments = -1

是否有其他方法获取模板参数或我做错了什么?

光标类似乎没有关于其参数的任何信息,至少在本例中是这样;我不知道为什么。但是
FIELD\u DECL
有一个可以有模板参数的
类型。下面是一个经过最小修改的代码版本,它为示例代码中的
vec\u of_ints
字段打印模板参数的数量:

import sys
import clang.cindex
clang.cindex.Config.set_library_file("/usr/lib/llvm-6.0/lib/libclang.so.1")

class Walker:
    def __init__(self, filename):
        self.filename = filename

    def walk(self, node):
        node_in_file =  bool(node.location.file and node.location.file.name == self.filename)
        if node_in_file:
            print(f"node.spelling = {node.spelling:14}, node.kind = {node.kind}")
            # -------- BEGIN modified section --------
            type = node.type
            if type is not None:
                ntargs = type.get_num_template_arguments()
                if ntargs > 0:
                    print(f"  type.spelling = {type.spelling}")
                    print(f"  type.get_num_template_arguments = {ntargs}")
            # -------- END modified section --------
        for child in node.get_children():
            self.walk(child)

filename = sys.argv[1]
index = clang.cindex.Index.create()
translation_unit = index.parse(filename)

root = translation_unit.cursor
walker = Walker(filename)
walker.walk(root)
在示例输入文件上运行时,我得到:

node.spelling = outer_t       , node.kind = CursorKind.STRUCT_DECL
node.spelling = vec_of_ints   , node.kind = CursorKind.FIELD_DECL
  type.spelling = std::vector<int>
  type.get_num_template_arguments = 1
node.spelling = std           , node.kind = CursorKind.NAMESPACE_REF
node.spelling = vector        , node.kind = CursorKind.TEMPLATE_REF
node.spelling=outer\u t,node.kind=CursorKind.STRUCT\u DECL
node.spelling=vec\u of\u int,node.kind=CursorKind.FIELD\u DECL
type.spelling=std::vector
type.get\u num\u模板\u参数=1
node.spelling=std,node.kind=CursorKind.NAMESPACE\u REF
node.spelling=vector,node.kind=CursorKind.TEMPLATE\u REF
我并不声称这将处理所有出现在代码中的模板的情况。我通过反复试验和阅读库模块源文件发现了上述内容。但它有望成为一个有用的起点

在任何情况下,关于ClangAST(以及几乎所有C/C++AST)需要了解的一件重要事情是类型不是主语法树中的节点。更确切地说,类型是对树中某些节点的语义解释,因此有点偏向一边。这就是为什么它们不会显示为
walk
的参数

node.spelling = outer_t       , node.kind = CursorKind.STRUCT_DECL
node.spelling = vec_of_ints   , node.kind = CursorKind.FIELD_DECL
  type.spelling = std::vector<int>
  type.get_num_template_arguments = 1
node.spelling = std           , node.kind = CursorKind.NAMESPACE_REF
node.spelling = vector        , node.kind = CursorKind.TEMPLATE_REF