libclang Python Bindings
libclang provides Python bindings for Clang, the LLVM project's C, C++, and Objective-C compiler front-end. It allows programmatic access to Clang's AST (Abstract Syntax Tree), diagnostics, and other compiler functionalities. The `libclang` PyPI package, currently at version 18.1.1, mirrors the official LLVM project's Python bindings to simplify installation and is released in sync with major LLVM versions.
Warnings
- gotcha Shared Library Not Found (`SharedLibraryNotFound`) is the most common error. While the `libclang` PyPI package attempts to auto-configure the library path when installed via wheels, this can fail in custom environments (e.g., development setups, using a system-installed LLVM, or manual Python installations).
- breaking API changes in the underlying Clang C API are directly reflected in the `libclang` Python bindings. Upgrading to a new major `libclang` version (e.g., from 17.x to 18.x) may introduce breaking changes in function signatures, enum values, or object structures.
- breaking The `libclang` Python bindings are primarily designed for Python 3. Support for Python 2.x has been dropped in recent LLVM versions, and wheels for older Python versions are no longer provided.
- gotcha Performance considerations when parsing large codebases. Creating an `Index` and `TranslationUnit` can be resource-intensive, and traversing large ASTs can be slow.
Install
-
pip install libclang
Imports
- Index
from clang.cindex import Index
- CursorKind
from clang.cindex import CursorKind
- Config
from clang.cindex import Config
Quickstart
from clang.cindex import Index, TranslationUnit
# Source code to parse
source_code = """
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
printf("Sum: %d\n", add(5, 3));
return 0;
}
"""
# Create an index
index = Index.create()
# Parse the source code from a string. For files, use Index.parse('path/to/file.c')
tu = index.parse('test.c', unsaved_files=[('test.c', source_code)])
# Check for diagnostics (errors/warnings)
for diagnostic in tu.diagnostics:
print(f"Diagnostic: {diagnostic}")
# Iterate through the AST to find functions
print("\nFunctions found:")
for cursor in tu.cursor.get_children():
if cursor.kind == TranslationUnit.CursorKind.FUNCTION_DECL:
print(f" Function: {cursor.spelling}, return type: {cursor.result_type.spelling}")
for arg in cursor.get_arguments():
print(f" Argument: {arg.spelling}, type: {arg.type.spelling}")
print("\nFirst 10 tokens:")
for token in tu.get_tokens(extent=tu.cursor.extent)[:10]:
print(f" Token: '{token.spelling}' (kind: {token.kind})")