如何用Python在Clang中获取变量或参数的类型全名?
使用libclang获取变量/参数的完整类型全名
要获取成员变量、函数参数的带命名空间限定的完整类型名(比如将private B* b解析为nm::B*,void f(B& var)解析为void (nm::B&)),核心思路是绕过代码中的using namespace声明,直接从类型的语义声明中提取完全限定名,再拼接类型修饰符。以下是具体实现方案:
核心辅助函数:获取类型的完全限定名
实现一个递归函数,处理各种类型(基本类型、用户定义类型、指针、引用、数组等)的完全限定名解析:
#include <string> #include <iostream> #include "clang-c/Index.h" std::string getFullyQualifiedType(CXType type) { // 提取const/volatile限定符 bool isConst = clang_isConstQualifiedType(type); bool isVolatile = clang_isVolatileQualifiedType(type); // 递归处理复合类型的底层类型,再拼接修饰符 switch (type.kind) { // 指针类型 case CXType_Pointer: { CXType pointee = clang_getPointeeType(type); std::string pointeeName = getFullyQualifiedType(pointee); std::string result = pointeeName + "*"; if (isConst) result = "const " + result; if (isVolatile) result = "volatile " + result; return result; } // 左值/右值引用 case CXType_LValueReference: case CXType_RValueReference: { CXType pointee = clang_getPointeeType(type); std::string pointeeName = getFullyQualifiedType(pointee); std::string refSuffix = (type.kind == CXType_LValueReference) ? "&" : "&&"; std::string result = pointeeName + refSuffix; if (isConst) result = "const " + result; if (isVolatile) result = "volatile " + result; return result; } // 数组类型 case CXType_ConstantArray: case CXType_VariableArray: { CXType elementType = clang_getElementType(type); std::string elementName = getFullyQualifiedType(elementType); CXString sizeStr = clang_getArraySizeSpelling(type); std::string size = std::string(clang_getCString(sizeStr)); clang_disposeString(sizeStr); std::string result = elementName + "[" + size + "]"; if (isConst) result = "const " + result; if (isVolatile) result = "volatile " + result; return result; } // 函数原型(处理函数指针等情况) case CXType_FunctionProto: { CXType returnType = clang_getResultType(type); std::string returnName = getFullyQualifiedType(returnType); unsigned int numArgs = clang_getNumArgTypes(type); std::string argsStr; for (unsigned int i = 0; i < numArgs; ++i) { CXType argType = clang_getArgType(type, i); if (i > 0) argsStr += ", "; argsStr += getFullyQualifiedType(argType); } std::string result = returnName + "(" + argsStr + ")"; if (isConst) result = "const " + result; if (isVolatile) result = "volatile " + result; return result; } // 基本类型或用户定义类型 default: { CXCursor declCursor = clang_getTypeDeclaration(type); // 基本类型(如int、void)直接返回拼写 if (clang_isInvalid(clang_getCursorKind(declCursor))) { CXString typeSpelling = clang_getTypeSpelling(type); std::string result = std::string(clang_getCString(typeSpelling)); clang_disposeString(typeSpelling); if (isConst) result = "const " + result; if (isVolatile) result = "volatile " + result; return result; } // 用户定义类型:遍历语义父节点拼接命名空间 std::string qualifiedName; CXCursor parent = clang_getCursorSemanticParent(declCursor); while (clang_getCursorKind(parent) == CXCursor_Namespace) { CXString parentName = clang_getCursorSpelling(parent); if (!qualifiedName.empty()) { qualifiedName = std::string(clang_getCString(parentName)) + "::" + qualifiedName; } else { qualifiedName = std::string(clang_getCString(parentName)); } clang_disposeString(parentName); parent = clang_getCursorSemanticParent(parent); } // 拼接类型名 CXString typeName = clang_getCursorSpelling(declCursor); std::string baseName = std::string(clang_getCString(typeName)); clang_disposeString(typeName); if (!qualifiedName.empty()) { qualifiedName += "::" + baseName; } else { qualifiedName = baseName; } // 添加限定符 if (isConst) qualifiedName = "const " + qualifiedName; if (isVolatile) qualifiedName = "volatile " + qualifiedName; return qualifiedName; } } }
获取成员变量的类型全名
遍历AST找到CXCursor_FieldDecl类型的游标(对应类的成员变量),调用上述辅助函数即可:
void processClassMember(CXCursor cursor) { if (clang_getCursorKind(cursor) != CXCursor_FieldDecl) return; CXType fieldType = clang_getCursorType(cursor); std::string fullType = getFullyQualifiedType(fieldType); // 输出结果:例如对于private B* b,会输出nm::B* std::cout << "成员变量类型:" << fullType << std::endl; }
获取函数的完整签名(含参数类型全名)
找到CXCursor_FunctionDecl类型的游标,解析返回类型和每个参数的类型,拼接成完整签名:
void processFunction(CXCursor cursor) { if (clang_getCursorKind(cursor) != CXCursor_FunctionDecl) return; CXType funcType = clang_getCursorType(cursor); // 解析返回类型 CXType returnType = clang_getResultType(funcType); std::string returnFullType = getFullyQualifiedType(returnType); // 解析参数列表 unsigned int numArgs = clang_getNumArgTypes(funcType); std::string argsStr; for (unsigned int i = 0; i < numArgs; ++i) { CXType argType = clang_getArgType(funcType, i); if (i > 0) argsStr += ", "; argsStr += getFullyQualifiedType(argType); } // 拼接完整签名:例如void (nm::B&) std::string fullSignature = returnFullType + "(" + argsStr + ")"; std::cout << "函数完整签名:" << fullSignature << std::endl; }
关键注意事项
- 绕过using声明:通过语义父节点遍历,直接从类型的原始声明中提取命名空间,不受代码中
using namespace的影响。 - 内存管理:libclang返回的
CXString必须用clang_disposeString释放,避免内存泄漏。 - 覆盖所有类型场景:函数已处理指针、引用、数组、函数指针、const/volatile限定符等常见类型修饰。
内容的提问来源于stack exchange,提问作者heLomaN
相关产品推荐
相关产品推荐

