Java解析c/c++ 的.h文件中的结构体
1.引入CDT工具包
<dependency>
<groupId>org.eclipse.core</groupId>
<artifactId>org.eclipse.core.resources</artifactId>
<version>3.7.100</version>
</dependency>
<dependency>
<groupId>com.github.mhoffrog.attached</groupId>
<artifactId>org.eclipse.cdt.core</artifactId>
<version>5.11.0</version>
</dependency>
2.实现代码
2.1初始化
@SneakyThrows
public List<CStructDeclaration> readStructCpp(String filePath) {
CppFileParser parser;
try {
parser = new CppFileParser(filePath);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return parser.getStructDeclaration();
}
2.2解析头文件信息
private File headerFile;
private IASTTranslationUnit unit;
public CppFileParser(String headerFilePath) throws Exception {
headerFile = new File(headerFilePath);
if (!headerFile.exists()) {
throw new IllegalArgumentException("The header file don't exists");
}
unit = getTranslationUnit(headerFile);
functions = new ArrayList<>();
}
IASTTranslationUnit getTranslationUnit(File source) throws Exception {
FileContent reader = FileContent.create(source.getAbsolutePath(), getContentFile(source).toCharArray());
return GPPLanguage.getDefault().getASTTranslationUnit(reader,
new ScannerInfo(), IncludeFileContentProvider.getSavedFilesProvider(), null,
ILanguage.OPTION_IS_SOURCE_UNIT, new DefaultLogService());
}
String getContentFile(File file) throws IOException {
StringBuilder builder = new StringBuilder();
String line;
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
while ((line = br.readLine()) != null) {
builder.append(line).append("\n");
}
}
return builder.toString();
}
2.3结构体解析
public List<CStructDeclaration> getStructDeclaration() {
List<CStructDeclaration> cStructDeclarationList = new ArrayList<>();
IASTDeclaration[] declarations = unit.getDeclarations();
for (IASTDeclaration declaration : declarations) {
if (declaration instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration;
IASTDeclSpecifier declSpecifier = simpleDeclaration.getDeclSpecifier();
if (declSpecifier instanceof IASTCompositeTypeSpecifier) {
IASTCompositeTypeSpecifier compositeTypeSpecifier = (IASTCompositeTypeSpecifier) declSpecifier;
if (compositeTypeSpecifier.getKey() == IASTCompositeTypeSpecifier.k_struct) {
String structName = compositeTypeSpecifier.getName().toString();
System.out.println("找到结构体: " + structName);
CStructDeclaration cStructDeclaration = new CStructDeclaration();
cStructDeclaration.setName(structName);
List<CStructMember> cStructMemberList = new ArrayList<>();
IASTDeclaration[] structMembers = compositeTypeSpecifier.getMembers();
for (IASTDeclaration member : structMembers) {
if (member instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration memberDeclaration = (IASTSimpleDeclaration) member;
IASTDeclarator[] declarators = memberDeclaration.getDeclarators();
for (IASTDeclarator declarator : declarators) {
IASTPointerOperator[] pointerOperators = declarator.getPointerOperators();
if (pointerOperators.length > 0) {
StringBuilder pointerType = new StringBuilder();
for (IASTPointerOperator pointer : pointerOperators) {
pointerType.append(pointer.getRawSignature());
}
IASTName memberNames = declarator.getName();
String memberNameString = memberNames.toString();
IASTDeclSpecifier memberTypeSpecifier = memberDeclaration.getDeclSpecifier();
String memberTypeName = memberTypeSpecifier.getRawSignature();
System.out.println(
" 成员变量: " + memberTypeName + pointerType + " " + memberNameString);
CStructMember cStructMember = new CStructMember();
cStructMember.setType(memberTypeName + pointerType);
cStructMember.setName(memberNameString);
cStructMember.setArray(Boolean.FALSE);
cStructMemberList.add(cStructMember);
} else {
IASTName memberName = declarator.getName();
IASTDeclSpecifier memberTypeSpecifier = memberDeclaration.getDeclSpecifier();
String memberTypeName = memberTypeSpecifier.getRawSignature();
String memberNameString = memberName.toString();
if (declarator instanceof IASTArrayDeclarator) {
IASTArrayModifier[] arrayModifiers =
((IASTArrayDeclarator) declarator).getArrayModifiers();
if (arrayModifiers.length > 0) {
IASTExpression iastExpression =
arrayModifiers[0].getConstantExpression();
if (Objects.isNull(iastExpression)) {
System.out.println(
" 成员变量: " + memberTypeName + " " + memberNameString + "[]");
CStructMember cStructMember = new CStructMember();
cStructMember.setType(memberTypeName);
cStructMember.setName(memberNameString + "[]");
cStructMember.setArray(Boolean.TRUE);
cStructMember.setArraySize(0);
cStructMemberList.add(cStructMember);
} else {
int arraySize = Integer.parseInt(iastExpression.getRawSignature());
System.out.println(
" 成员变量: " + memberTypeName + " " + memberNameString + "[" + arraySize + "]");
CStructMember cStructMember = new CStructMember();
cStructMember.setType(memberTypeName);
cStructMember.setName(memberNameString + "[" + arraySize + "]");
cStructMember.setArray(Boolean.TRUE);
cStructMember.setArraySize(arraySize);
cStructMemberList.add(cStructMember);
}
}
} else {
System.out.println(
" 成员变量: " + memberTypeName + " " + memberNameString);
CStructMember cStructMember = new CStructMember();
cStructMember.setType(memberTypeName);
cStructMember.setName(memberNameString);
cStructMember.setArray(Boolean.FALSE);
cStructMemberList.add(cStructMember);
}
}
}
}
}
cStructDeclaration.setCStructMembers(cStructMemberList);
cStructDeclarationList.add(cStructDeclaration);
}
}
}
}
return cStructDeclarationList;
}
2.4结构体实体
@Data
public class CStructDeclaration {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("名称")
private String name;
@ApiModelProperty("结构体参数")
private List<CStructMember> cStructMembers;
}
@Data
public class CStructMember {
@ApiModelProperty("id")
private String id;
@ApiModelProperty("结构体id")
private Long structId;
@ApiModelProperty("字段名称")
private String name;
@ApiModelProperty("字段类型")
private String type;
@ApiModelProperty("是否为数组。0否 1是")
private Boolean array;
@ApiModelProperty("数组长度")
private Integer arraySize;
}
3.解析接口
public List<CFunctionDeclaration> getFunctionDeclaration() throws IOException {
IASTDeclaration[] decs = unit.getDeclarations();
unit = parseCPP(getContentFile(headerFile));
ASTNamesVisitor namesVisitor = new ASTNamesVisitor();
unit.accept(namesVisitor);
for (IASTName iastName : namesVisitor.getNames()) {
if (!(iastName.resolveBinding() instanceof ICPPFunction)) {
continue;
}
ICPPFunction function = (ICPPFunction) iastName.resolveBinding();
List<CFunctionParameter> parameters = new ArrayList<>();
for (ICPPParameter arg : function.getParameters()) {
CFunctionParameter param = CFunctionParameter.builder()
.type(arg.getType().toString())
.rawDeclaration(arg.getType().toString() + " " + arg.getName())
.name(arg.getName())
.build();
if (arg.getType() instanceof CPPPointerType) {
param.setPointer(true);
}
parameters.add(param);
}
CFunctionDeclaration funDecl = new CFunctionDeclaration(
function.getType().getReturnType().toString() + " " + function,
function.getType().getReturnType().toString(),
function.getName(),
parameters
);
functions.add(funDecl);
}
functions.forEach(fun -> {
System.out.printf(" Func, declaration: %s, returnType:%s, name:%s, parameters:\n", fun.getRawDeclaration(),
fun.getReturnType(), fun.getName());
fun.getParameters().stream().forEach(p -> {
System.out.printf(" raw :%s, type:%s, name:%s, isPoint:%b\n", p.getRawDeclaration(), p.getType(),
p.getName(), p.isPointer());
});
});
return functions;
}
@Data
public class CFunctionDeclaration {
private String returnType;
private String name;
private List<CFunctionParameter> parameters;
private String rawDeclaration;}
@Data
@Builder
public class CFunctionParameter {
private String type;
private String name;
private String rawDeclaration;
private boolean isPointer;
}