C++ header (and source) parser for Python using Clang plugins.
-
Get the required tools:
-
You'll need to have clang-11 and the required dev tools installed.
To install using
apton Debian / Ubuntu see LLVM Debian/Ubuntu nightly packages page. -
Note that pyheaders requires Python>=3.8.
-
-
Clone pyheaders:
Change the directory to where you want the pyheaders installer directory placed.
git clone https://github.com/Roynecro97/pyheaders.git
-
Build the plugins:
cd pyheaders ./update-plugin.sh -
Install pyheaders:
From the pyheaders directory run:
python setup.py install
Or to install in develop mode:
python setup.py develop
-
You can now safely erase the git clone (unless pyheaders is installed in develop mode).
pyheaders can be imported and used as a module.
It provides 3 main functions: load_path, load and loads.
All 3 functions return a pyheaders.SrcData object that has 2 properties:
scope- The C++ global scope that was parsed from the provided code.macros- A dictionary with all non-function macros that were generated.
Both load and loads behave similarly to the similarly named functions in the json and pickle modules.
Using load:
Assuming source.cpp contains the line
static constexpr int x = 100;
import pyheaders
with open('source.cpp') as f:
data = pyheaders.load(f)
print(data.scope['x'])Output:
100
Using loads:
import pyheaders
cpp_code = '''\
namespace constants {
inline constexpr auto greeting = "Hello World!";
}
'''
scope, macros = pyheaders.loads(cpp_code, ['-std=c++17'])
print(scope['constants::greeting'])Output:
Hello World!
Using load_path:
load_path provides a useful alternative when working with big projects as it accepts the path to a C++ file or a directory that contains C++ source code and loads it.
Using this method allows pyheaders to find your project's compile_commands.json if it exists and read the compilation flags from there implicitly.
Assuming src/ contains a file with:
class MyClass { // code ... static constexpr int magic = 0x10; // code ... };
import pyheaders
scope = pyheaders.load_path('src/').scope
print(scope['MyClass::magic'])Output:
16
NOTE: When using load or loads pyheaders will look for a compile_commands.json file from the current working directory.
NOTE: When using load or loads and when a file processed by load_path is missing from the compile_commands.json, but the compile commands were successfully loaded, pyheaders will attempt to find a close match in the compile commands and use flags that are common among all commands.
This mechanism allows pyheaders to find the include path (for example) for a header file (that is not compiled on its own).
pyheaders can also be used as an executable by running python -m pyheaders or simply pyheaders.
Example usage:
$ cat << EOF > a.cpp
namespace project
{
static constexpr auto greeting = "Hello from pyheaders!";
}
EOF
$ pyheaders get a.cpp --const project::greeting --hide-names
'Hello from pyheaders!'