当前位置: 首页 > news >正文

记录java调用eclipse cdt 解析c++文件

环境:

jdk1.8

eclipse cdt  9.11.1

需求: 

java 解析c++中的类,属性类型,属性名称,函数,函数参数,返回值。

注意点: 

如果你是外网编码,移植依赖和代码到内网的时候

运行可能出现 class not found xxxx ,  这个依赖其实是对的。

解决办法: 

将内网的maven的setting.xml 与外网的仓库地址相同就能解决

具体需要一致内容地点: 

      <mirror><id>aliyunmaven</id><mirrorOf>*</mirrorOf><name>阿里云公共仓库</name><url>https://maven.aliyun.com/repository/public</url></mirror>

  

依赖: 

1. cdt 下载
https://archive.eclipse.org/tools/cdt/releases/9.11/cdt-9.11.1/

2. pom添加依赖: 

<dependencies><!-- CDT 核心 --><dependency><groupId>org.eclipse.cdt</groupId><artifactId>org.eclipse.cdt.core</artifactId><version>9.11.1</version><scope>system</scope><systemPath>${project.basedir}/libs/org.eclipse.cdt.core_6.11.1.202006011430.jar</systemPath></dependency><!-- Eclipse runtime 必要依赖 --><dependency><groupId>org.eclipse.platform</groupId><artifactId>org.eclipse.core.runtime</artifactId><version>3.13.0</version></dependency><dependency><groupId>org.eclipse.platform</groupId><artifactId>org.eclipse.core.jobs</artifactId><version>3.9.3</version></dependency><dependency><groupId>org.eclipse.platform</groupId><artifactId>org.eclipse.core.contenttype</artifactId><version>3.6.0</version></dependency><dependency><groupId>org.eclipse.platform</groupId><artifactId>org.eclipse.equinox.common</artifactId><version>3.9.0</version></dependency><!-- 日志服务 --><dependency><groupId>org.eclipse.platform</groupId><artifactId>org.eclipse.equinox.supplement</artifactId><version>1.8.0</version></dependency></dependencies>

 

解析代码: 

package org.example;import org.eclipse.cdt.core.dom.ast.*;
import org.eclipse.cdt.core.dom.ast.cpp.*;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.*;import java.util.HashMap;public class CDTParseExample {public static void main(String[] args) throws Exception {// 1. 指定要解析的头文件路径String filePath = "C:\\Users\\dell\\AppData\\Roaming\\JetBrains\\IntelliJIdea2025.2\\extensions\\xxxxxx.h";FileContent fileContent = FileContent.createForExternalFileLocation(filePath);// 2. 模拟 include / 宏定义信息  HashMap<String, String> macros = new HashMap<>();macros.put("__cplusplus", "1");macros.put("XXXXX_DLL", "");  // 避免 class XXXXX_DLL 出错macros.put("FRDTOMOON_ID", "int");  // 如果有类似 typedef 也要补macros.put("CAbstractEntity", "int"); // 临时占位macros.put("C_DBIDriver", "int");macros.put("CTableQuery", "int");IScannerInfo scannerInfo = new ScannerInfo(macros, new String[] {"C:\\Users\\dell\\AppData\\Roaming\\JetBrains\\IntelliJIdea2025.2\\extensions"});IncludeFileContentProvider fileContentProvider = IncludeFileContentProvider.getEmptyFilesProvider();// 3. 创建 TranslationUnitIASTTranslationUnit translationUnit = GPPLanguage.getDefault().getASTTranslationUnit(fileContent,scannerInfo,fileContentProvider,null,ITranslationUnit.AST_PARSE_INACTIVE_CODE,new DefaultLogService());// 4. 遍历 AST,找到类定义// 假设你已经有 IASTTranslationUnit tu(通过 GPPLanguage.getDefault().getASTTranslationUnit(...))translationUnit.accept(new ASTVisitor(true) {{// 一定要打开这些 flagshouldVisitDeclarations = true;shouldVisitDeclSpecifiers = true;shouldVisitNamespaces = true;// 如果头文件内有宏可能屏蔽成员,考虑打开:
//                 includeInactiveNodes = true;}// 处理命名空间(可选)@Overridepublic int visit(ICPPASTNamespaceDefinition namespaceDefinition) {System.out.println("namespace: " + (namespaceDefinition.getName() != null ? namespaceDefinition.getName() : "<anon>"));// namespace 内部声明也会单独触发 visit(IASTDeclaration),// 这里可以选择直接遍历 namespaceDefinition.getDeclarations() 或交由 visit(IASTDeclaration) 处理。return PROCESS_CONTINUE;}@Overridepublic int visit(IASTProblem problem) {System.out.println("Parser problem: " + problem.getMessage()+ " at " + problem.getFileLocation().getFileName()+ ":" + problem.getFileLocation().getStartingLineNumber());return PROCESS_CONTINUE;}// 处理所有声明(包括 class/struct 的声明)@Overridepublic int visit(IASTDeclaration declaration) {// 只关心简单声明(class/struct 在 simpleDecl 的 declSpec 中)if (declaration instanceof IASTSimpleDeclaration) {IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) declaration;IASTDeclSpecifier declSpec = simpleDecl.getDeclSpecifier();// 如果这是 class/struct 的定义(复合类型)if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {ICPPASTCompositeTypeSpecifier classSpec = (ICPPASTCompositeTypeSpecifier) declSpec;System.out.println("Class/Struct: " + classSpec.getName());// 关键点:成员就在 classSpec.getMembers()IASTDeclaration[] members = classSpec.getMembers();for (IASTDeclaration member : members) {// 我们主要关心成员变量(IASTSimpleDeclaration 且 declarators 非空 且 不是函数)if (member instanceof IASTSimpleDeclaration) {IASTSimpleDeclaration memberDecl = (IASTSimpleDeclaration) member;IASTDeclarator[] decs = memberDecl.getDeclarators();if (decs != null && decs.length > 0) {// 如果 declarator 不是函数 declarator,则为字段if (!(decs[0] instanceof IASTFunctionDeclarator)) {String type = memberDecl.getDeclSpecifier() != null ?memberDecl.getDeclSpecifier().getRawSignature() : "<unknown>";for (IASTDeclarator d : decs) {// 安全取名(有时 getName() 为空)String name = (d.getName() != null) ? d.getName().toString() : d.getRawSignature();System.out.println("  field: " + name + " | type: " + type);}}}}// 如果成员是函数定义,也可以在这里处理(可选)else if (member instanceof IASTFunctionDefinition) {IASTFunctionDefinition fd = (IASTFunctionDefinition) member;String fname = fd.getDeclarator() != null && fd.getDeclarator().getName() != null ?fd.getDeclarator().getName().toString() : "<anon>";System.out.println("  method-def: " + fname);}}}// 如果这是顶层 enum(也可能出现在类内)else if (declSpec instanceof ICPPASTEnumerationSpecifier) {// 可按需处理}}// 另外,如果遇到类外的函数定义(有函数体),也可以处理else if (declaration instanceof IASTFunctionDefinition) {// 处理类外限定名的函数定义(例如 CAbstractRead::serialize)IASTFunctionDefinition funcDef = (IASTFunctionDefinition) declaration;IASTFunctionDeclarator fd = funcDef.getDeclarator();if (fd != null) {System.out.println("Top-level function def: " + fd.getName());}}return PROCESS_CONTINUE;}});// 5. 从 binding 里提取字段for (IASTDeclaration decl : translationUnit.getDeclarations()) {if (decl instanceof IASTSimpleDeclaration) continue;if (decl instanceof ICPPASTCompositeTypeSpecifier) {ICPPASTCompositeTypeSpecifier cls = (ICPPASTCompositeTypeSpecifier) decl;ICPPClassType binding = (ICPPClassType) cls.getName().resolveBinding();if (binding != null) {System.out.println("类名: " + binding.getName());for (ICPPField field : binding.getDeclaredFields()) {System.out.println("成员变量: " + field.getName() +" , 类型: " + field.getType().toString());}}}}}private static void handleClassMember(IASTDeclaration member) {if (member instanceof IASTSimpleDeclaration) {IASTSimpleDeclaration memberDecl = (IASTSimpleDeclaration) member;IASTDeclarator[] declarators = memberDecl.getDeclarators();if (declarators.length == 0) return;// 变量if (!(declarators[0] instanceof IASTFunctionDeclarator)) {String type = memberDecl.getDeclSpecifier().getRawSignature();for (IASTDeclarator d : declarators) {String name = d.getName().toString();System.out.println("  字段: " + name + " | 类型: " + type);}}}}}

  

代码注意点: 

//上面代码中的这里可以把 c++里面的宏跳过定义处理,如果你的头文件有定义宏,并且没有在这put上,可能会解析失败
HashMap<String, String> macros = new HashMap<>();

  

 

http://www.jsqmd.com/news/4012/

相关文章:

  • Chormium 密码管理器表单结构体说明(基于Chromium138)
  • 为什么人工智能选择Python?深入解析AI界的胶水语言
  • 1 day(20250925) - when
  • 12分钟讲解Python核心理念
  • 【重要】什么是 PEP 8 规范
  • 实用指南:华为坤灵:点燃中小企业智能化的星火
  • 阻止HTML input元素(type=number)中输入字母e的方法
  • 【Prompt学习技能树地图】利用GitHub-Prompt Engineering Guide进阶学习Prompt工程指南 - 指南
  • 深入解析:KRaft 运维从静态到动态 Controller
  • Windows时间同步列表注册表授时时间服务器
  • epub如何让标题在竖直方向居中
  • Apple Books 对 epub 支持的限定(未完待续)
  • 完整教程:区间dp,数据结构优化dp等6种dp,各种trick深度讲解
  • win10开机输入密码后一直转圈,很长时间才登录到桌面
  • Windows11 右键菜单管理
  • Mac 安装PDF2zh
  • 完整教程:leetcode (2)
  • 如何通过 Python + Selenium + BeautifulSoup 爬取动态加载的网页数据 - 教程
  • 实用指南:【连载6】 C# MVC 日志管理最佳实践:归档清理与多目标输出配置
  • 2025Unity必备知识——GUI(完整详细) - 指南
  • HBM之父:HBM的终点是HBF
  • 实用指南:40.应用层协议HTTP(三)
  • 【GitHub每日速递 250926】12 周 24 课,边学边练!微软 AI 初学者的通关秘籍
  • mcp-use mcp server 交互工具
  • 年薪破百万、涨薪60%,人形机器人企业疯狂「抢人」
  • 深入解析:HttpClientFactory vs new HttpClient:.NET Core HTTP 客户端的正确打开方式
  • 华为投的这家上海独角兽,要IPO了!
  • 0134_委托模式 (Delegate)
  • Java 与交通科技:智慧交通与自动驾驶实践
  • 读人形机器人23政府的角色