Python Tkinter embedded in C++ thread

Viewed 313

I have a C++ project that I would like to add an embedded python interpreter to. I've actually succeeded in this with simple scripts, but when I try doing something with Tkinter, it opens a blank window and never draws any frame or contents. I'm pretty sure it has to do with the GIL, but have been unsuccessful in finding some combination of calls that work. I've made a simple example that illustrates this with a C++ file and a python script that the compiled program runs. If you uncomment the MyPythonThread line and comment out the two that run it in a thread, then it works as expected.

It seems python knows whether it is in the "main" thread or not, regardless of which thread I Py_Initialize from.

Other info.: I'm testing this on Mac OS X 10.13.6 with homebrew installed python 2.7.15.

//
// Compile with: g++ `python-config --cflags --libs` --std=c++11 test.cc
//

#include <cstdio>
#include <Python.h>
#include <thread>

void MyPythonThread(void)
{
    PyEval_InitThreads();
    Py_Initialize();

    const char *fname = "test.py";
    PySys_SetArgv( 1, (char**)&fname );
    auto fil = std::fopen(fname, "r");
    PyRun_AnyFileEx( fil, NULL, 1 );

}

int main(int narg, char * argv[])
{

    // This works
//  MyPythonThread();

    // This does not
    std::thread thr(MyPythonThread);
    thr.join();

    return 0;
}

Here is the python script that it runs:

#!/usr/bin/env python

import Tkinter as tk

window = tk.Tk()
top_frame = tk.Frame(window).pack()
b1 = tk.Button(top_frame, text = "Button").pack()

window.mainloop()
0 Answers
Related