记录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. 创建 TranslationUnit
        IASTTranslationUnit 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) {
            {
                // 一定要打开这些 flag
                shouldVisitDeclarations = true;
                shouldVisitDeclSpecifiers = true;
                shouldVisitNamespaces = true;
                // 如果头文件内有宏可能屏蔽成员,考虑打开:
//                 includeInactiveNodes = true;
            }

            // 处理命名空间(可选)
            @Override
            public int visit(ICPPASTNamespaceDefinition namespaceDefinition) {
                System.out.println("namespace: " + (namespaceDefinition.getName() != null ? namespaceDefinition.getName() : "<anon>"));
                // namespace 内部声明也会单独触发 visit(IASTDeclaration),
                // 这里可以选择直接遍历 namespaceDefinition.getDeclarations() 或交由 visit(IASTDeclaration) 处理。
                return PROCESS_CONTINUE;
            }

            @Override
            public int visit(IASTProblem problem) {
                System.out.println("Parser problem: " + problem.getMessage()
                        + " at " + problem.getFileLocation().getFileName()
                        + ":" + problem.getFileLocation().getStartingLineNumber());
                return PROCESS_CONTINUE;
            }


            // 处理所有声明(包括 class/struct 的声明)
            @Override
            public 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<>();

  

 

posted @ 2025-09-26 08:55  沙师弟demo  阅读(7)  评论(0)    收藏  举报