Interactive application wrapped with SWIG
Rob McDonald <[email protected]> Thu, 13 Jan 2022 16:20:25 -0800
| Newsgroups | gmane.comp.programming.swig |
|---|---|
| Message-ID | <CAEppYpGLPzPDwVhAGdevdC6i_VL8OKoU-5PMU_RAGn0vJ1JoaA@mail.gmail.com> |
Apologies for the long setup to this question, hopefully someone will bear with me and will be able to help. I have a C++ program that has an API wrapped with SWIG. Users commonly use SWIG generated Python bindings. This program is not written to be thread safe. For all reasonable purposes, it is a single threaded application. My program has a GUI (FLTK based) including 3D visualization with OpenGL. It has been designed such that the core computation engine can be compiled without the GUI and OpenGL code and all the dependencies. That version can be executed on a computer with no graphics libraries or OpenGL drivers installed. If the normal version of the application is called 'app_g' (with graphics), then the no-graphics version might be called 'app_ng'. Similarly, when I build the SWIG bindings, I can build '_api_ng.so' and '_api_g.so' versions. Today, users of the Python bindings use the no-graphics version import api_ng as foo foo.bar() # etc. The application and API are designed such that nearly all state is stored on the C++ side of things. Large and complex objects are not passed back through the bindings, only relatively simple (and small) data is passed through the interface. My understanding is that when Python encounters the 'import' line, it creates an instance of my program and keeps it active in memory. It then lies dormant until it receives a command via 'foo.bar()' or whatever. Long ago, we also allowed users to import the graphical version of the bindings along with some added commands... import api_g as foo foo.StartGUI() # etc. Here, the 'StartGUI()' call would launch the application's GUI and then start its event loop. The user could then interact normally with the GUI. When they were finished, they would close the window. When the window was closed, we would exit the event loop -- but we would not terminate the program, exit(), or free memory. This way, control would be returned to Python. In this way, a Python program could use the API, or it could provide an interactive GUI to the user. However, it could not do both at once. I say long ago because we had trouble getting this to work properly on one platform and we ended up disabling the feature without ever tracing down the problem. We've lived happily without it for about a decade. We regularly build on Windows, Mac, and Linux as well as some BSD and other *NIX. We do not currently build on any phones, tablets, game consoles, embedded platforms, etc. Now I have a use case where I want to use the GUI while the API is being accessed. However, unlike before, we would like the GUI to be accessible simultaneously with the Python environment making API calls -- or going on doing something else. I think the way to accomplish this goal is to have the call to StartGUI() launch the event loop in a separate thread. A single lock is implemented to make access thread safe. When any GUI event occurs, the lock is checked out when execution leaves the event loop. That event is handled and the lock is released when execution returns to the event loop. Similarly, every API call needs to check out and return the lock. When an API call is made, it will first check out the lock -- waiting until it is released by the GUI if needed. Once it has the lock, it will execute the desired command, releasing the lock when done. While this is a very coarse-grained approach to locking, it seems the most reasonable approach initially. I believe it will suffice, but it may be possible to move to a more fine grained locking arrangement sometime later. Depending on how long the lock is checked out by the API, it might make sense to add some visual queue to the GUI -- say a red/green box in the corner indicating whether execution lies with the API or is free for the user to interact. Now for the question... Is this the right approach? Is there something fundamentally wrong with this idea? Can anyone point me at an example application that takes this approach? Thanks in advance for any help, Rob _______________________________________________ Swig-user mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/swig-user