redirect sys.stdout to C++ ?

André Jonsson tatsujin at despammed.com
Sun Dec 29 09:10:30 EST 2002


Bengt Richter wrote:
> 
> On Sat, 28 Dec 2002 19:43:21 +0100, =?ISO-8859-1?Q?Andr=E9_Jonsson?= 
> <tatsujin at despammed.com> wrote:


<cutting long and _very_ informative post>

> It seems to be working. So what did I do differently from what you did?
> Maybe the fflush in logwrite?

Hm... it seems the problem is somehow related to the buffering I do in the C++ 
application.

I simplified your example to just echo to stdout of the C app, instead of to a file. 
And surely enough it worked quite allright. So I then modified the redirection python 
class in my code to handle the buffering, instead of the C++ log function (like in 
your example), and that was it, now it works!!

Though I don't yet understand why the buffering in C++ could cause a newline 
character to be "lost" from the not-yet-handled input string. I would guess I have a 
rogue pointer somewhere...

Anyway, I'm greatly thankful for your help! It probably would've taken a lot longer 
on my own... probably until I rewrote the whole shebang or something.

/André



Here's my version of the test code (all in one file):
--------------------------------------------------------------------------------------
#include <stdio.h>
#include <Python.h>
#include <string.h>

int logwrite(char *line)
{
	int newline=line[strlen(line)-1]=='\n';
	if(newline)
		line[strlen(line)-1]='\0';
	printf("logwrite(\"%s%s\")\n", line, newline?"\\n":"");
	return 0;
}

static PyObject *andre_log(PyObject *self, PyObject *args)
{
	char *s_line;
	if (!PyArg_ParseTuple(args, "s:andrelog", &s_line))
		return NULL;

	Py_BEGIN_ALLOW_THREADS
	logwrite(s_line);
	Py_END_ALLOW_THREADS

	Py_INCREF(Py_None);
	return Py_None;
}

static PyMethodDef andreMethods[] = {
	{"andre_log", (PyCFunction)andre_log, METH_VARARGS,
	 "andre_log(line) writes a log message"},
	{NULL, NULL, 0, NULL}
};

int main(int argc, char *argv[])
{
	char *prompt = "Enter Python line: ";
	char line[128];
	
	Py_Initialize();
	Py_InitModule("andreApp", andreMethods);

	PyRun_SimpleString(""
			"import andreApp     # a module interface created by C application\n"
			"class Logger:\n"
			"    def __init__(self):\n"
			"        self.buf = []\n"
			"    def write(self, data):\n"
			"        self.buf.append(data)\n"
			"        if data.endswith('\\n'):\n"
			"            andreApp.andre_log(''.join(self.buf))\n"
			"            self.buf = []\n"
			"\n"
			"import sys\n"
			"sys.stdout = Logger()\n"
			"#sys.stderr = Logger()\n"
			"");
	
	while(1)
	{
		printf(prompt);
		if(fgets(line, 128, stdin) == NULL)
			break;

		line[strlen(line)-1]='\0'; // cut newline character
  		printf("main()  entered: \"%s\"\n", line);
		PyRun_SimpleString(line);
	}
	Py_Finalize();
	return 0;
}

--------------------------------------------------------------------------------------

 > ./pytest
Enter Python line: print '1'
main()  entered: "print '1'"
logwrite("1\n")
Enter Python line: print '1'
main()  entered: "print '1'"
logwrite("1\n")


The problem was that the last newline was missing...





More information about the Python-list mailing list