I am writing a bytecode interpreter in C for a simple programming language.
I want to add GUI capabilities to the language. As a first step, I decided to bake into the interpreter a wrapper for the GTK library. It is exposed to user code as a builtin module.
My problem is that GTK works by taking control of the thread: once you call the C function g_application_run
, the thread enters an endless listening loop inside GTK.
Why is this a problem? Because while we are "stuck" in this GTK loop, the bytecode interpretation loop of the interpreter is frozen. Psuedo bytecode to demonstrate:
0 SOME OPCODE
1 SOME OTHER OPCODE
2 OPCODE INVOKING GTK WRAPPER FUNCTION <-- GTK invoked in C level and enters an endless loop
3 MORE OPCODES <-------- This is never executed
My first thought to combat this, was to design my GTK wrapper in a "close to 1:1 mirroring" style to the way the C library is supposed to be used. For example in psuedo code:
import gtk
func app_code() {
# ... app code ...
}
gtk.application_run(app_code)
This supposedly solves the problem - we don't care that we never exit the GTK endless loop inside g_application_run
, because it is now its responsibility to invoke our own user code.
The reason this won't work: the way user functions are invoked inside the interpreter, is by
- Pushing a new stack frame on the call stack
- Setting the instruction pointer to point to the beginning of the called functions bytecode
- In the next iteration of the bytecode interpretation loop, the new function will naturally start running
The GTK wrapper can easily do steps 1 and 2. But - step 3 will never happen, because we are stuck inside the GTK infinite loop. The interpreter loop never begins a new iteration.
So my question is: what are the possible options to solve this issue? Preferably, what are examples of how this issue is dealt with in existing projects?
- Start the GTK loop on a different C level thread?
- Forsake GTK and look for a less "framework-y" and more "library-y" type of GUI toolkit, that doesn't take thread control?
- Any other options?