Parser Backends¶
autopxd2 supports two parser backends. libclang is strongly recommended for all use cases.
Available Backends¶
libclang (Recommended)¶
Uses LLVM's clang library for parsing. Provides the same parser used by production compilers.
Pros:
- Full C++ support (classes, templates, namespaces)
- Extracts macros as constants (integers, floats, strings, expressions)
- Automatic system include path detection
- Handles comments and preprocessor directives directly
- Better error messages
- Handles complex headers reliably
Cons:
- Requires libclang to be installed
- Python
clang2package version must match system libclang (these are official LLVM bindings) - Slightly slower startup time
- Function-like macros are not extracted
Usage:
System Include Paths¶
The libclang backend automatically detects system include directories by querying the system clang compiler. This means headers like <stddef.h> and <stdint.h> work without requiring manual -I flags.
To disable automatic include detection:
You can still add additional include directories:
pycparser (Legacy)¶
A pure Python C99 parser. Falls back to this if libclang is not available.
Legacy Backend
pycparser is maintained for backwards compatibility but is not recommended. It lacks C++ support, macro extraction, and circular dependency handling.
Cons:
- C99 only (no C++ support)
- No macro extraction
- No circular dependency handling
- Requires preprocessed code
- May struggle with complex headers
Usage:
Choosing a Backend¶
Use libclang for everything. The only reason to use pycparser is if you cannot install LLVM on your system.
| Use Case | Recommended Backend |
|---|---|
| C headers | libclang |
| C++ headers | libclang |
| Headers with macros | libclang |
| Complex library headers | libclang |
| Cannot install LLVM | pycparser (fallback) |
Backend Comparison¶
Both backends produce equivalent output for standard C constructs:
Both backends produce:
Macro Extraction (libclang only)¶
The libclang backend extracts #define macros as Cython constant declarations. The type is automatically detected from the macro value.
Integer Macros¶
Generates int declarations:
Supported formats: decimal, hex (0x), octal (0), binary (0b), with optional type suffixes (U, L, UL, LL, ULL).
Floating-Point Macros¶
Generates double declarations:
String Macros¶
Generates const char* declarations:
Expression Macros¶
Expression macros that consist of numeric literals, operators, and other macro references are detected and declared with appropriate types:
Unsupported Macros (silently ignored)¶
- Function-like macros:
#define MAX(a, b) ((a) > (b) ? (a) : (b)) - Empty macros:
#define EMPTY - String concatenation:
#define CONCAT "hello" "world"
The pycparser backend does not extract macros since it requires preprocessed input.
C++ Template Support (libclang only)¶
The libclang backend supports C++ templates, including primary templates and full specializations.
Primary Templates¶
C++ class templates with type parameters are translated to Cython's template syntax:
Generates:
Multiple type parameters are supported:
template<typename K, typename V>
class Map {
public:
V lookup(K key);
void insert(K key, V value);
};
Generates:
Template Specializations¶
Full template specializations are emitted with mangled Python-safe names and the original C++ name as a string literal:
Generates:
The mangling scheme converts special characters to valid Python identifiers:
- < and > are removed, contents become underscore-separated
- * becomes _ptr
- & becomes _ref
- :: becomes _
Examples:
- Container<int> → Container_int
- Map<int, double> → Map_int_double
- Foo<int*> → Foo_int_ptr
Using Docker for libclang¶
If you don't want to install libclang locally, use the Docker image:
See Docker Usage for details.