我正在尝试使用 clang 及其 python 绑定(bind)来处理 C/C++ 代码的 AST。
我有以下测试 C++ 代码:
#include <stdio.h>
class myclass {
public:
void mymethod() {
printf("method\n");
}
};
void testfunc() {
myclass var;
var.mymethod();
}
我编写了以下 python 代码(简化和缩短)来遍历它:
#! /usr/bin/python
import clang.cindex
import sys
def walk(node):
if node.kind == clang.cindex.CursorKind.CALL_EXPR:
print 'name: %s, type: %s' % (node.spelling or node.displayname, node.type.spelling)
for c in node.get_children():
walk(c)
index = clang.cindex.Index.create()
walk(index.parse(sys.argv[1]).cursor)
现在,当我的代码在 testfunc 中到达 var.mymethod() 时,它显示“mymethod”和“void”。不是我所期望的。我正在尝试检索调用 mymethod 的类类型,而不是方法的返回类型。
最佳答案
如上面的评论所述,您将获得函数的返回类型。这不是调用 mymethod
的变量类型。
查看AST输出(使用clang -Xclang -ast-dump -fno-diagnostics-color),这是testfunc
的定义
`-FunctionDecl 0x5e14080 <line:9:1, line:12:1> line:9:6 testfunc 'void ()'
`-CompoundStmt 0x5e14750 <col:17, line:12:1>
|-DeclStmt 0x5e146b0 <line:10:9, col:20>
| `-VarDecl 0x5e14130 <col:9, col:17> col:17 used var 'myclass' callinit
| `-CXXConstructExpr 0x5e14680 <col:17> 'myclass' 'void () noexcept'
`-CXXMemberCallExpr 0x5e14728 <line:11:9, col:22> 'void'
`-MemberExpr 0x5e146f0 <col:9, col:13> '<bound member function type>' .mymethod 0x5e13dd0
`-DeclRefExpr 0x5e146c8 <col:9> 'myclass' lvalue Var 0x5e14130 'var' 'myclass'
然后您可以看到在 CXXMemberCallExpr
内部,您有一个 MemberExpr
并且在其中有一个 DeclRefExpr
返回到 var
及其类型 myclass
。我不确定您究竟是如何用 Python 编写它的,但是通过从 CALL_EXPR 条目中转储一些内部结构,应该不会很难弄清楚。
使用上面的代码,我将其修改为如下所示:
#! /usr/bin/python
import clang.cindex
import sys
def find_decl_ref_expr(node):
for c in node.get_children():
if c.kind == clang.cindex.CursorKind.DECL_REF_EXPR:
print "Member function call via", c.type.spelling, c.displayname
else:
find_decl_ref_expr(c)
def called_from(node):
for c in node.get_children():
if c.kind == clang.cindex.CursorKind.MEMBER_REF_EXPR:
find_decl_ref_expr(c);
def walk(node):
if node.kind == clang.cindex.CursorKind.CALL_EXPR:
print 'name: %s, type: %s' % (node.spelling or node.displayname, node.type.spelling)
called_from(node)
for c in node.get_children():
walk(c)
index = clang.cindex.Index.create()
walk(index.parse(sys.argv[1]).cursor)
它有点管用,但绝对不是一个完整的解决方案。例如,添加一个通过数组使用的指针也会打印用于进入数组的索引。为了完全理解复杂代码,我不确定您实际需要做什么 [例如如果 myclass
是具有各种指针和索引操作的类的几层]。
我还发布了一些代码,我用它来检查每个节点中的内容:
def dump_children(node):
for c in node.get_children():
print c.kind, c.type.spelling
dump_children(c)
关于python - clang python 绑定(bind) : how to find type of a variable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48750406/