如何使用libclang获取AST字符串并借助CXUnsavedFile遍历AST?
实现libclang基于内存代码直接遍历AST的方案
不需要预先导出.ast文件,直接把待处理代码作为内存缓存传递给libclang的clang_parseTranslationUnit接口,配合CXUnsavedFile结构体即可完成内存中translationUnit的创建,全程无磁盘IO,实现逻辑如下:
1. 初始化libclang索引
索引是所有libclang操作的基础,先创建CXIndex实例:
// 第一个参数:是否排除本地声明,第二个参数:是否显示诊断信息,可按需调整 CXIndex index = clang_createIndex(0, 0);
2. 构造CXUnsavedFile实例
该结构体用于传递内存中未持久化到磁盘的代码内容:
CXUnsavedFile unsaved_file; // 自定义文件名,后缀需要和代码语法规则匹配(比如.c/.cpp后缀对应C/C++代码) unsaved_file.Filename = "demo.cpp"; // 内存中存储的待处理代码内容 unsaved_file.Contents = R"( #include <iostream> int main() { std::cout << "Hello World" << std::endl; return 0; } )"; // 代码内容的字节长度 unsaved_file.Length = strlen(unsaved_file.Contents);
如果需要同时处理多个内存文件,构造多个CXUnsavedFile组成数组传递即可。
3. 解析生成TranslationUnit
调用解析接口直接基于内存代码生成translationUnit:
// 编译选项,和clang/gcc编译参数完全一致,按需调整 const char* compile_args[] = {"-x", "c++", "-std=c++17"}; int num_args = sizeof(compile_args) / sizeof(compile_args[0]); CXTranslationUnit tu = clang_parseTranslationUnit( index, unsaved_file.Filename, // 对应上一步定义的文件名 compile_args, num_args, // 编译选项数组和数量 &unsaved_file, 1, // 未保存文件数组和数量,单个文件填1即可 CXTranslationUnit_None // 解析选项,可按需调整 );
如果解析返回空tu,可调用clang_getDiagnostic接口查看具体错误信息,常见原因是编译选项和代码类型不匹配、代码存在语法错误。
4. 遍历AST
拿到的translationUnit和基于.ast文件生成的tu用法完全一致,正常遍历即可:
CXCursor root_cursor = clang_getTranslationUnitCursor(tu); clang_visitChildren(root_cursor, [](CXCursor cursor, CXCursor parent, CXClientData client_data) { // 自定义遍历逻辑,示例为打印节点类型和节点名称 CXString kind_spelling = clang_getCursorKindSpelling(clang_getCursorKind(cursor)); CXString cursor_spelling = clang_getCursorSpelling(cursor); printf("节点类型:%s,节点名称:%s\n", clang_getCString(kind_spelling), clang_getCString(cursor_spelling)); clang_disposeString(kind_spelling); clang_disposeString(cursor_spelling); return CXChildVisit_Recurse; }, nullptr);
5. 资源释放
操作完成后释放对应资源避免内存泄漏:
clang_disposeTranslationUnit(tu); clang_disposeIndex(index);
常见说明
- 如果代码依赖自定义头文件,可在编译选项中加
-I指定头文件搜索路径,用法和正常编译参数完全一致 - 针对不同语言的代码,修改编译选项中的
-x参数即可,比如C代码改为-x c、Objective-C代码改为-x objective-c
内容的提问来源于stack exchange,提问作者Onkar Dahale
相关产品推荐
相关产品推荐

