Problem using Juce in a Python module

Hi,

I am quite new to Juce, and I am already blocked by an issue.

I'd like to make a python module that opens a Juce Window when the module is imported (by the 'import <module>" , which calls a C function :  PyMODINIT_FUNC PyInit_<module>(void) ).

As it must create a new thread I can not use of course the standard JuceApplication initialisation, with START_JUCE_APPLICATION and so.

It looks like it is not more possible to use ScopedJuceInitialiser_GUI + MessageManager::runDispatchLoop() elsewhere than in the main thread.

I made a lot of tries, without any success : no gui displaying, and abort trap.

So here are my questions : Do you think this is something possible ? and if yes, how ?

 

Everything's possible! Sounds like you're on the right lines, but I've no idea how python modules work, hopefully someone else will be able to help out here..

My question is not particulary related to Python, it could be another kind of embedding.

It is quite simple, the Juce GUI initialisation must be called in a standard C function, like this one (PyInit_MyModule) :

static std::thread* my_juce_thread;

void my_juce_gui_initialisation_and_loop(){
   initialiseJuce_GUI(); // is it enough ???
   {
     DocumentWindow main_window("MyWindow", Colours::white, true, true); 

     // don't know what to write here, in any case JuceApplication can not be used in a thread
     // a MessageManager loop ???
   }
   shutdownJuce_GUI();
}

PyObject* PyInit_MyModule(void){

   // code to declare the new python module, new_module_pyobject_ptr

   PyObject* new_module_pyobject_ptr = ...

   // entering a new thread :

   my_juce_thread = new std::thread(my_juce_gui_initialisation_and_loop);

   return new_module_pyobject_ptr;

}

The question here can be summarised to : what should I write in my initialisation and loop function (my_juce_gui_initialisation_and_loop) ?
 

 

 

Yes, calling that initialiser function is enough. But do you really need to run the message thread via juce, or is there already some other service that's doing that?

For MacOS it does not seem to be enough. It works better with:

#if JUCE_MAC 
  JUCE_AUTORELEASEPOOL { 
   [NSApplication sharedApplication]; 
  } 
#endif

The main window also needs a runModalState() loop or something similar, isn't it ?

It worked when I tried from the main thread, but not within a new thread : the window is displayed, but blank, without any content drawn, and is not responding to mouse events.

void my_juce_gui_initialisation_and_loop(){ 
   
   #if JUCE_MAC 
     JUCE_AUTORELEASEPOOL { [NSApplication sharedApplication]; } 
   #endif

   initialiseJuce_GUI(); 
   { 
      DocumentWindow main_window("MyWindow", Colours::white, true, true); 
      //...

      main_window.runModalLoop();

   } 
   shutdownJuce_GUI(); 
}

 

When all of these is embedded in a python module, I have to do all the threading stuff, otherwise the python interpreter will be blocked by the GUI loop.

 

I read that in MacOS there is no way to make a GUI loop elswhere than in the application main thread.

So it looks like my idea to open a window inside a Python module (that launches a new thread) is just impossible.