Skip to main content

ecpz - Evaluate C++ using Python and Zig

Do you need to evaluate some simple C++ code from inside your application, and it should work cross-platform (Linux, Mac and Windows) without causing a headache?

You've seen it all, quine-relay stopped being amusing years ago, and you feel the itch for something new?

No problem, easy-peasy with ecpz!


This little package combines the ubiquity of Python and ingeniuity of the Zig toolchain to give you the ability to compile C++ snippets without pain.

If you have a non-trivial project consisting of more than one source file, you should probably configure and build it properly using e.g. CMake.

If you need an interactive C++ code execution environment (i.e. a REPL), check out cling.

But if for some reason you need to produce and execute some ad-hoc throw-away C++ snippets as a part of your workflow, ecpz might be just what you need!

Usage

Install ecpz using pip or uv and check ecpz --help for all options.

In the following, the features of ecpz are illustrated by some examples.

ecpz run

Compile and run a single source file provided either as argument or via standard input.

For example, create hello.cpp:

#include <print>

int main() {
  std::println("Hello world!");
}

And run it:

$ cat hello.cpp | ecpz --clang-arg -std=c++23 run
Hello world!

ecpz print

Evaluates some expressions and pretty-print them using std::print(ln) (note that this automatically implies -std=c++23).

For example, create a header prelude.hpp:

#include <numbers>
#include <type_traits>

inline double tau() {
  return 2 * std::numbers::pi;
}

And now run:

$ ecpz --prelude prelude.hpp print "{:.3f} {} {} {}" "tau()" "[](){ int i=0; ++i; return i; }()" "std::is_same_v<int, double>" "std::is_same_v<int, int32_t>"
6.283 1 false true

You can set the ECPZ_PRELUDE environment variable to the path of your custom header to make it always included by default. Note that as usual, CLI arguments override equivalent environment variables.

Creating a Quine

Usually, using I/O to let code open itself directly is forbidden and considered bad sportsmanship. Everybody agrees that the following things are clear cases of cheating:

  • reading a hard-coded string filename
  • using the argv[0] trick to reflect back the name of the current file/executable
  • reading the file using some compile- or runtime reflection capabilities of the programming language
  • adding and using a special quine command in a custom programming language or environment

We will do none of these things. Create some source file FILE with the following content:

#include "ecpz/subprocess.hpp"
int main(int i, char** a) {
    using b = std::istreambuf_iterator<char>; using c = std::string;
    auto d = [](auto e){ std::ifstream f(e, std::ios::binary); return c(b(f), b()); };
    std::vector<c> e(i+3, a[i-1]); e[0]="ecpz"; e[1]="run";
    auto f = i%2 == 0 ? subprocess::run(e).output : d(a[i-1]);
    subprocess::set_bin(); std::cout<<f;
}

Now run it with ecpz run FILE FILE and convince yourself that we do not cheat in such despicable and reprehensible ways as the ones listed above!

Spoiler

Nobody ever said that we cannot just...

  • run a C++ source file through ecpz,
    • which uses a Python package,
      • which provides the zig toolchain,
        • which provides clang,
    • to compile and then run the program, which
      • runs its arguments through ecpz,
        • compiling and then running the same program, which now finally
          • prints the file passed to it as the argument

Or, at least I did not get the memo that this is illegal. In that case I apologize for wasting your time.

But even if this is still cheating - isn't cheating in glorious ways not also a form of art?

Limitations

The following issues are fixable, i.e. only a matter of more effort and time:

  • currently only synchronous execution is supported, no I/O buffering or streaming
  • currently it is not possible to pipe input data into ecpz run to pass it as stdin

Acknowledgements

Thanks to sheredom for creating subprocess.h, the only true header-only C(++) subprocess library I could find!

Metadata

Release files for ecpz 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ecpz 0.1.0
File Size Uploaded
ecpz-0.1.0.tar.gz 17.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ecpz 0.1.0
File Interpreter ABI Platform
ecpz-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.5 kB

Release files / ecpz-0.1.0.tar.gz

Download URL ecpz-0.1.0.tar.gz
Size 17.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9a32d5bcb20e0fa9f120d059f54fff2397c090834d5f3a7bfdecdc8279d06944
BLAKE2b-256 checksum
How to use checksums
3e528b0ad6cf03d54368809738f38f910fe762d3da4f8bd03939cb91469a2c39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Release files / ecpz-0.1.0-py3-none-any.whl

Download URL ecpz-0.1.0-py3-none-any.whl
Size 17.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
229cf66966eb51eb71ce067dedd545930a044a33c0b9e88c0b9383744ec6c82c
BLAKE2b-256 checksum
How to use checksums
5ea0ffade4de74bcce08e1eeef855844a8702c9b0a858a15e4a8976bb6963b9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page