I'm testing to see if it's possible to embed python in a wxWindows c++ program as a simple interpreter. The interpreter will have a *very* simple idle like interface and I will add functions to hook in the c++ data structures. But, alas I have some problems and questions and after digging through python/wxPython/(anything I could find including both python and this newgroup) I can't find suitable answers.
1) I need to redirect stdout, stderr, and stdin. stdout/err are easy to do and I create events. The stdin, seems far more tricky. In fact I don't believe that wxPython does this? PyCrust does it on a python level, but don't you need to do it at the c++ level too?
The Ctrl-C problem that people have mentioned is probably because you don't call PyOS_FiniInterrupts() which stops python from "stealing" stdin. I'm guessing what happens is that ctrl-c kills the python interpreter and then your wxPython app crashes the next time it tries to use it.
Here is some simple code to redirect the stdio and setup python to use these instead, "wxstdio" uses the function below this python code (the stdout function is not shown).
PyRun_SimpleString("import wxstdio\n"
"sys.oldstdin = sys.stdin\n"
"sys.oldstdout = sys.stdout\n"
"sys.oldstderr = sys.stderr\n"
"class StdioRedir:\n"
" def write(self, text):\n"
" wxstdio.stdout(text)\n"
" def write(self, s, tags=(), mark='insert'):\n"
" wxstdio.stdout(s)\n"
" def writelines(self, l):\n"
" map(self.write, l)\n"
" def read(self, length = None):\n"
" return wxstdio.stdin()\n"
" def readline(self, length = None):\n"
" return wxstdio.stdin()\n"
" def readlines(self, length = None):\n"
" return wxstdio.stdin()\n"
" def __del__(self):\n" // restore stdio
" sys.stdin = sys.oldstdin\n"
" sys.stdout = sys.oldstdout\n"
" sys.stderr = sys.oldstderr\n"
// redirect stdio to the class
"sys.stdin = StdioRedir()\n"
"sys.stdout = StdioRedir()\n"
"sys.stderr = StdioRedir()\n");
This is my c function for stdin, I know it's nonsense, but what can I do? I'd like to send it real keycodes, for example ctrl-c and stuff mapped from a textctrl's OnChar...
static PyObject *pyStdin(PyObject *WXUNUSED(self), PyObject* args)
{
//printf("My stdin!!!\n"); fflush(stdout);
wxString msg;
// this merely searches for an instance of the wxPythonInterpreter class that has a matching PyThreadState
wxPythonInterpreter *pI = wxPythonInterpreter::FindInterpreter(PyThreadState_Get());
if (pI)
{
// m_stdinString gets filled from a textctrl
msg = pI->m_stdinString;
pI->m_stdinString.Clear();
}
return PyString_FromString(msg.c_str());
}
ps. the embedded.cpp sample should proabably have
"sys.stdout = sys.stderr = output\n\"
instead of
"sys.stdin = sys.stderr = output\n\"
2) Lets say someone types while(1) : print "hi". I need to stop that gracefully, but I don't see anyway to get a hook into python. Some languages have methods to pause/break the interpreter and the also have callbacks that can be setup to be called every n number of instructions. This would be useful since I'd like to run python in a wxThread and I need to check TestDestroy(). Python doesn't seem to have either of these unless I'm mistaken. This seems like a serious problem since it would be easy enough to "take out" a program with a trivial mistake in a python script. You can try that code in PyCrust and after a few seconds it segfaults. The segfault I assume is from the textctrl overflowing (which is easy to solve), but before that happens you cannot stop it.
Anyway, maybe I'm neurotic since nobody else (code from python newsgroups and others) seems to care about runaway python programs embedded into a c program.
I would appreciate any insight, Thanks.
John Labenski