thanks for the tips. I was looking at coroutines -- that was my first choice since I had experience implementing them in a small embedded system. Unfortunately, the portable implementation (libpcl) requires one to guess the stack size required. Not a good thing for an interpreter, where arbitrary user scripts can be run. Also, libpcl is Unix-only, I think.
Threads are also a pain, because one has to design a communication protocol, which makes debugging much more difficult. This application has to be rock-solid (as opposed to high performance), and I'm afraid I don't have time to completely iron out any bugs in a multithreaded application. So, I'll go with the scheme I initially presented which, if it works, has the advantage of not requiring any OS-dependent libraries.
> -----Original Message-----
> From: Jeroen van der Zijp [mailto:
jeroen@...]
> Sent: Tuesday, May 26, 2009 2:45 PM
> To:
foxgui-users@...
> Cc: Hardy, Stephen
> Subject: Re: [Foxgui-users] Running interpreter from FOX
>
> On Tuesday 26 May 2009, Hardy, Stephen wrote:
> > Hi all,
> >
> > I need to run Python from a FOX app, and would like to implement a
> simple debug facility (like single stepping through the Python code and
> putting breakpoints). Python has a "pdb" class for just this sort of
> thing. pdb, however, is console-based but I don't want to bother my
> users with a command-line.
> >
> > Python has the ability to invoke a callback function (in C or C++)
> for each line executed, and several other useful events.
> Unfortunately, it does not have an easy way of executing line-by-line
> directly under the caller's control. In other words, one must either
> return normally from the callback in order to process the next line, or
> throw an exception in the callback to halt the whole thing. There's no
> API that can simply be called to execute one (and only one) line.
> >
> > The FOX question is this: could I invoke FXApp::runWhileEvents()
> within the Python trace callback? Considering that the main app loop
> is already running, is this recursive invocation OK? Reading the
> documentation, I don't see any reason why not, but it doesn't hurt to
> ask.
> >
> > Here is a more detailed scenario: suppose there is a text widget that
> has the Python code, and buttons which say "run", "stop" and "pause".
> "run" starts interpreting the code, and "stop" should always cancel it,
> and "pause" is a temporary halt so local variables can be examined etc.
> In all cases, the rest of the application should be active (no wait
> cursors or modal dialogs!).
> >
> > . The "run" button handler sets a run flag if pressed, and registers
> the following chore.
> > . The "stop" button handler clears the run and pause flags.
> > . The "pause" button handler sets a pause flag.
> >
> > In the chore:
> > . if run flag is set, call PyRun...() which invokes the following
> callback for each line.
> > . clear the run flag (because script terminated)
> >
> > In the Python trace callback:
> > . do {
> > . call FXApp::runWhileEvents()
> > . (In this recursive invocation of the event loop, the run and
> pause flags may be manipulated.)
> > . } while (pause flag)
> > . If the run flag is not set then we throw an exception, otherwise we
> just return.
> >
> > I'm hoping this will work. Anyone see any problems?
> >
> > Is it best to invoke the event loop from within a chore, or would a
> normal FOX "onCmd..." handler be OK?
>
> Interleaving Python's exec loop and FOX's event loop seems best. You
> can use chores, which will basically
> run some python code whenever there are no immediately pressing events
> from the GUI.
>
> I do suggest to look at other solutions:
>
> 1) Make your program multi-threaded. In that case, the python
> interpreter would run in a separate
> thread.
> Interfacing between Python and FOX must be done via
> FXMessageChannel, of course.
>
> 2) Another solution is cooperative task switching AKA coroutines.
> I believe there are ways to do
> this, last time I looked.
> This is like threads, in that each coroutine has its own stack
> space etc. but unlike threads
> the coroutines switch instruction steams synchronously, by
> calling an explicit function to
> transfer control.
>
> Significant advantage of this approach is that no complex
> synchronization methods are needed
> for the coroutines to communicate.
>
> Look for "portable coroutines" library.
>
>
> If I were to seriously consider something like this I'd look really
> hard at coroutines or threads...
>
>
> Regards,
>
> - Jeroen
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals. Meet
Group, R/GA, & Big Spaceship.