Poznámka: Viz také naši vylepšenou verzi tohoto příspěvku, Jak exportovat pole C++ struct do JSON pomocí clang a boost::json.
Viz také Jak parsovat C++ komentáře ze zdrojového kódu pomocí clang
Knihovna clang poskytuje poměrně snadný způsob, jak parsovat C/C++ kód a extrahovat informace o struct definicích.
Následující kód demonstruje, jak parsovat následující struct definici:
parse_struct.cpp
typedef struct {
double a; /* Ten zvláštní parametr */
double b; /* Další zvláštní parametr */
} myParameters;Úplný zdrojový kód
parse_struct_full.cpp
#include <clang-c/Index.h>
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
void extractStructFields(CXCursor cursor) {
CXCursorKind kind = clang_getCursorKind(cursor);
if (kind == CXCursor_StructDecl) {
CXString structName = clang_getCursorSpelling(cursor);
std::cout << "Struktura: " << clang_getCString(structName) << std::endl;
clang_disposeString(structName);
clang_visitChildren(cursor, [](CXCursor c, CXCursor parent, CXClientData client_data) {
CXCursorKind kind = clang_getCursorKind(c);
if (kind == CXCursor_FieldDecl) {
CXString fieldName = clang_getCursorSpelling(c);
CXType fieldType = clang_getCursorType(c);
CXString typeName = clang_getTypeSpelling(fieldType);
std::cout << " Pole: " << clang_getCString(fieldName) << " (Typ: " << clang_getCString(typeName) << ")" << std::endl;
clang_disposeString(fieldName);
clang_disposeString(typeName);
}
return CXChildVisit_Continue;
}, nullptr);
}
}
int main() {
CXIndex index = clang_createIndex(0, 0);
const char *code = R"(
typedef struct {
double a; /* Ten zvláštní parametr */
double b; /* Další zvláštní parametr */
} myParameters;
)";
CXUnsavedFile unsavedFile = {"test.cpp", code, (unsigned long)strlen(code)};
CXTranslationUnit unit = clang_parseTranslationUnit(index, "test.cpp", nullptr, 0, &unsavedFile, 1, CXTranslationUnit_None);
if (unit == nullptr) {
std::cerr << "Nepodařilo se parsovat překladovou jednotku." << std::endl;
return 1;
}
CXCursor cursor = clang_getTranslationUnitCursor(unit);
clang_visitChildren(cursor, [](CXCursor c, CXCursor parent, CXClientData client_data) {
extractStructFields(c);
return CXChildVisit_Continue;
}, nullptr);
clang_disposeTranslationUnit(unit);
clang_disposeIndex(index);
return 0;
}Jak zkompilovat
Na Ubuntu nainstalujte potřebné knihovny pomocí
install_libclang.sh
sudo apt -y install libclang-19-deva zkompilujte kód pomocí
build_parse_struct.sh
g++ parse_struct.cpp -o parse_struct -std=c++17 -I/usr/lib/llvm-19/include -L/usr/lib/llvm-19/lib -lclangPříklad výstupu
Spusťte pomocí ./parse_struct
parse_struct_output.txt
Struktura: myParameters
Pole: a (Typ: double)
Pole: b (Typ: double)Alternativní sestavení pomocí cmake
Možná budete muset upravit verze (19.1.1) a další parametry zde, aby to fungovalo správně pro vaše nastavení.
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(parse_structs)
# Nastavit standard C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Najít komponenty LLVM/Clang
find_package(LLVM 19.1.1 REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
# Přidat adresáře include
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${CLANG_INCLUDE_DIRS})
# Vytvořit spustitelný soubor
add_executable(parse_structs parse_structs.cpp)
# Přidat definice LLVM
target_compile_definitions(parse_structs PUBLIC ${LLVM_DEFINITIONS})
# Linkovat proti libclang
target_link_libraries(parse_structs PUBLIC libclang)
Podívejte se na podobné články podle kategorie:
C/C++ Clang Introspekce kódu
Pokud vám tento článek pomohl, zvažte, zda mi nekoupíte kávu nebo nepřispějete přes PayPal na podporu výzkumu a publikování nových článků na TechOverflow