Solarian Programmer My programming ramblings

This is a short tutorial about using Tkinter, the default Python GUI library, with OpenCV. On Windows, Tkinter is bundled with the official Python installer. On Linux, you can install Tkinter using your distribution package manager. The situation is a bit more complex on macOS, that comes with Python 2.7 and an old version of Tkinter, at the time of this writing, the easiest path is to install Miniconda Python 3 that comes with the latest Tkinter.

In my last article, I’ve shown you how to generate the machine code for a function at runtime, copy this code in a part of the memory, marked as executable, and call it from C++. Now, we’ll go the other way around, we’ll call a C++ function from a function generated at runtime. Like before, I assume that you try the code on Linux or macOS.

If you remember from part 1, we’ve started by adding machine code instructions in an std::vector and copying this code to an executable memory page. While this was a fine approach from a didactic point of view, in practice, you will probably want to write the code directly to the executable memory. Here is an example of how I propose to do it:

The object mp, from the above piece of code, will ask the OS for memory, release this memory when it is not needed and will have some helper member functions that will let us push pieces of machine code to the executable memory. We can also add safety features, e.g. a mechanism to check if we can push more data on the executable memory or if we’ve reached the bounds of the allocated memory pages.

For our purposes, JIT compilation is a technique through which a program generates machine code at runtime, based on the user input. A C++ program is AOT (ahead of time) compiled, which typically means that once the original code was compiled for a particular machine it can’t be changed at runtime (and from a security point of view this is a desirable feature). A simple, useful application, of a C++ JIT compiler is on the fly compilation of a new function that is based on other functions already defined in the original code.

The title of the presentation made me curious if I can optimize an old piece of code that used a huge 2D array of coefficients as the initial condition for a long calculation. In order to avoid recalculating the big array of coefficients, I used to keep them in a file and simply load the data in memory every time the code was executed. The promise of using a constexpr was that I could avoid keeping two executables (the code that generated the coefficients and the code that did the actual work) and a data file. Replacing everything with a single binary was interesting and could potentially be faster.

If you want to try the new C++17, using Clang in a Docker container, you are in the right place. Running Clang in a container has the advantage that it is light on resources and won’t mess with your underlying OS. The last point is especially important if your host operating system is macOS, on which it is a really bad idea to directly install a binary Clang other than the one that comes with Xcode. I’ve tested the approach presented in this article on Windows 10, macOS High Sierra and Ubuntu Linux.