Skip to content

Roynecro97/pyheaders

Repository files navigation

pyheaders

C++ header (and source) parser for Python using Clang plugins.

Installation

  1. Get the required tools:

    • You'll need to have clang-11 and the required dev tools installed.

      To install using apt on Debian / Ubuntu see LLVM Debian/Ubuntu nightly packages page.

    • Note that pyheaders requires Python>=3.8.

  2. Clone pyheaders:

    Change the directory to where you want the pyheaders installer directory placed.

    git clone https://github.com/Roynecro97/pyheaders.git
  3. Build the plugins:

    cd pyheaders
    ./update-plugin.sh
  4. Install pyheaders:

    From the pyheaders directory run:

    python setup.py install

    Or to install in develop mode:

    python setup.py develop
  5. You can now safely erase the git clone (unless pyheaders is installed in develop mode).

Using the Provided Module

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.

Using the Provided Functions

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).

Using the Provided Executable

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!'

About

C++ header (and source) parser

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published