【问题标题】:Expand macros & retrieve macro values展开宏并检索宏值
【发布时间】:2016-11-20 10:55:54
【问题描述】:

我正在尝试使用 libclang python 绑定来解析我的 c++ 源文件。我无法获取宏的值或扩展宏。
这是我的示例 C++ 代码

#define FOO 6001
#define EXPAND_MACR \
        int \
        foo = 61
int main()
{
    EXPAND_MACR;
    cout <<  foo;
    return 0;
}


这是我的python脚本

import sys
import clang.cindex

def visit(node):
    if node.kind in (clang.cindex.CursorKind.MACRO_INSTANTIATION,   clang.cindex.CursorKind.MACRO_DEFINITION):           
    print 'Found %s Type %s DATA %s Extent %s [line=%s, col=%s]' % (node.displayname, node.kind, node.data, node.extent, node.location.line, node.location.column)
for c in node.get_children():
    visit(c)

if __name__ == '__main__':
    index = clang.cindex.Index.create()
    tu = index.parse(sys.argv[1], options=clang.cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD)
    print 'Translation unit:', tu.spelling
    visit(tu.cursor)


这是我从 clang 那里得到的信息:

Found FOO Type CursorKind.MACRO_DEFINITION DATA <clang.cindex.c_void_p_Array_3 object at 0x10b86d950> Extent <SourceRange start <SourceLocation file 'sample.cpp', line 4, column 9>, end <SourceLocation file 'sample.cpp', line 4, column 17>> [line=4, col=9]
Found EXPAND_MACR Type CursorKind.MACRO_DEFINITION DATA <clang.cindex.c_void_p_Array_3 object at 0x10b86d950> Extent <SourceRange start <SourceLocation file 'sample.cpp', line 6, column 9>, end <SourceLocation file 'sample.cpp', line 8, column 11>> [line=6, col=9]
Found EXPAND_MACR Type CursorKind.MACRO_INSTANTIATION DATA <clang.cindex.c_void_p_Array_3 object at 0x10b86d950> Extent <SourceRange start <SourceLocation file 'sample.cpp', line 12, column 2>, end <SourceLocation file 'sample.cpp', line 12, column 13>> [line=12, col=2]


如果你观察我的 python 脚本,node.data 会给出

DATA <clang.cindex.c_void_p_Array_3 object at 0x10b86d950>


我可以读取 clang 返回的 Extent 数据,然后从 startend 位置解析文件以获取值。我想知道是否有更好的方法来获取宏值?
我想直接(不使用Extent)获取宏(示例中的6001)的值。我怎么能得到那个?
另外对于EXPAND_MACR 想得到int foo = 61

我已经看过这些帖子:Link-1 & Link-2
任何帮助将不胜感激

【问题讨论】:

    标签: python c++ clang libclang


    【解决方案1】:

    不,使用范围进行逐行扩展似乎是提取(扩展宏)的唯一方法。

    我怀疑问题在于,当 libclang 看到您的代码时,宏已被预处理器删除 - 您在 AST 中看到的节点更像是注释而不是真正的节点。

    #define FOO 6001
    #define EXPAND_MACR \
            int \
            foo = 61
    int main()
    {
        EXPAND_MACR;
        return 0;
    }
    

    真的是 AST

    TRANSLATION_UNIT sample.cpp
      +-- ...  *some nodes removed for brevity* 
      +--MACRO_DEFINITION FOO
      +--MACRO_DEFINITION EXPAND_MACR
      +--MACRO_INSTANTIATION EXPAND_MACR
      +--FUNCTION_DECL main
         +--COMPOUND_STMT 
            +--DECL_STMT 
            |  +--VAR_DECL foo
            |     +--INTEGER_LITERAL 
            +--RETURN_STMT 
               +--INTEGER_LITERAL 
    

    这相当于只运行预处理器(并告诉它为您提供所有预处理器指令的列表)。你可以通过运行看到类似的东西:

    clang -E -Wp,-dD src.cc
    

    这给出了:

    # 1 "<command line>" 1
    # 1 "<built-in>" 2
    # 1 "src.cc" 2
    #define FOO 6001
    #define EXPAND_MACR int foo = 61
    
    
    int main()
    {
        int foo = 61;
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      一种解决方法是创建另一个包含所有宏的文件

      Example.hpp

      #include "header_with_macro_ABC.h"
      
      auto abc = ABC:
      

      然后您可以再次解析此头文件以提取变量声明,并使用evaluate methods 获取值。

      优点:无需编写自己的表达式解析器。 缺点:需要创建和解析另一个文件。

      这种方法在很多情况下可能不可行,但对我来说,这是我必须解析 ffigen(Dart 的绑定生成器)的所有宏的时候。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-10
        相关资源
        最近更新 更多