Re: Multi-threaded wrapping
Rob McDonald <[email protected]> Thu, 29 Sep 2022 23:11:04 -0700
| Newsgroups | gmane.comp.programming.swig |
|---|---|
| Message-ID | <CAEppYpE8MmSxAGxKotCURBY6dJUN7WFnGsps6kY_VDxBTjZH4w@mail.gmail.com> |
Thanks for the help. This seems to have me off to a good start -- things are working remarkably well so far. Let's say my C++ code is called foo. And that the following is entered in a Python REPL: from threading import Thread import foo as foo t = Thread(target=foo.start_gui, args=()) t.start() This successfully loads foo, and then starts the event loop of foo's GUI in a separate thread. At this point, a user can interact with the foo GUI, or they can continue entering commands into the Python REPL. Let's say that the user wants to call one of foo's functions to do something. Like so... foo.dosomething() In this situation, foo's event loop GUI is still running in the other thread when foo.dosomething() is called. This generally seems to work so far. However, foo is not thread safe. Stand-alone foo is a single-threaded application. foo's GUI has a single lock. Every time interactive foo receives an event and goes to leave the event loop to handle the event, it acquires the lock. When the event is done being handled, the lock is released and control returns to the event loop to wait for the next event. So, to make this work, we would like to grab foo's GUI lock before executing dosomething() and then release it when complete. Is there a way to wrap every function / method wrapped with SWIG? I.e. add lock() and unlock() before/after every call? I've read the docs on code insertion <https://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIG_nn40>, but that seems to be at a bigger picture level (than every single call). But maybe I'm misunderstanding the docs. I can theoretically go through and modify every one of my API calls on the C++ side. I'd really rather not do that... For one, there are a lot of call sites -- this is will become a big maintenance burden to make sure all sites are modified and all future calls added also get this treatment. For two, this code is sometimes compiled without the GUI at all (and therefore no event loop and no lock). So all of the code would need to be #if conditional -- it will likely end up pretty ugly. I think it will be much more maintainable and much more clean if SWIG can take care of all of this in one place. Thanks again for any help, Rob On Tue, Sep 20, 2022 at 11:06 AM Burlen Loring <[email protected]> wrote: > the "-threads" option tells SWIG to release the GIL before entering > wrapped C++ code. This lets Python interpreter to continue to run while the > wrapped C++ code executes. However, this means that any calls made into the > Python C-API initiated from your wrapped code must first acquire the "GIL" > to prevent the interpreter state from becoming corrupted. Of course you > also need release GIL when done calling into the Python C-API. That's > pretty much all there is to it. > > For more info see: > > > https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock > https://www.swig.org/Doc4.0/Python.html#Python_multithreaded > > Also may be instructive to look at the code SWIG generates when you add > the -threads option. You can grep for the word THREAD in the C++ code SWIG > spits out. > > Hope this helps > > > On 9/19/22 09:48, William S Fulton wrote: > > > > On Mon, 12 Sept 2022 at 18:55, Rob McDonald <[email protected]> > wrote: > >> I have a C++ application with an event driven GUI (using FLTK) that is >> currently wrapped with Swig for Python. >> >> I can make calls (with no GUI loaded) to the exposed API. I can also >> launch the GUI from Python (and FLTK event loop) and interact with the >> graphical program for a while -- when satisfied, I can terminate the event >> loop to return control to Python. >> >> I would like to be able to leave the application GUI active (event loop >> still running) and return control to Python. The Python side might >> actually be a separate GUI with its own event loop. The two loops will >> need to communicate occasionally -- I can likely initiate all communication >> from the Python side. >> >> I believe I will need to run Swig with the 'threads' option. I also need >> to set up some sort of lock so the C++ event loop pauses when the C++ API >> is responding to a request from the Python side. >> >> Can anyone give any pointers on how to achieve this? Are there any >> examples of this available online? >> >> > There is an example of the 'threads' option in the SWIG test-suite. See > https://github.com/swig/swig/blob/master/Examples/test-suite/python_threads.i > with associated runtime test > https://github.com/swig/swig/blob/master/Examples/test-suite/python/python_threads_runme.py. > That's all I can find. > > William > > > _______________________________________________ > Swig-user mailing [email protected]://lists.sourceforge.net/lists/listinfo/swig-user > > > _______________________________________________ Swig-user mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/swig-user