
faulksp at iinet
May 2, 2012, 2:24 AM
Post #1 of 1
(75 views)
Permalink
|
|
The amazing disappearing stderr
|
|
G'day All, Following on from my earlier query on overloading print().... I've come up with this: /* < stdcallbk.pyd > */ /*---------------stdcallbk.h---------------------*/ #ifndef STDCALLBK_MODULE_H #include <Python.h> #define STDCALLBK_MODULE_H // Type definition for the callback function. typedef void __stdcall(CALLBK_FUNC_T)(const char* p); #ifdef __cplusplus extern "C" { #endif void register_callback(CALLBK_FUNC_T* callback); void import_stdcallbk(void); #ifdef __cplusplus } #endif #endif /* #define STDCALLBK_MODULE_H */ /*---------------stdcallbk.c---------------------*/ #include "stdcallbk_module.h" static CALLBK_FUNC_T *callback_write_func = NULL; static FILE *fp; /*for debugging*/ static PyObject* g_stdout; typedef struct { PyObject_HEAD CALLBK_FUNC_T *write; } Stdout; static PyObject* write2(PyObject* self, PyObject* args) { const char* p; if (!PyArg_ParseTuple(args, "s", &p)) return NULL; fputs(p, fp); fflush(fp); if(callback_write_func) callback_write_func(p); else printf("----%s----", p); return PyLong_FromLong(strlen(p)); } static PyObject* flush2(PyObject* self, PyObject* args) { // no-op return Py_BuildValue(""); } static PyMethodDef Stdout_methods[] = { {"write", write2, METH_VARARGS, "sys-stdout-write"}, {"flush", flush2, METH_VARARGS, "sys-stdout-write"}, {NULL, NULL, 0, NULL} }; static PyTypeObject StdoutType = { PyVarObject_HEAD_INIT(0, 0) "stdcallbk.StdoutType", /* tp_name */ sizeof(Stdout), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "stdcallbk.Stdout objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Stdout_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static struct PyModuleDef stdcallbkmodule = { PyModuleDef_HEAD_INIT, "stdcallbk", /* name of module */ NULL, /* module documentation, may be NULL */ -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ NULL, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_stdcallbk(void) { PyObject* m; fp = fopen("debuggered.txt", "wt"); fputs("got to here Vers 12\n", fp); fflush(fp); StdoutType.tp_new = PyType_GenericNew; if (PyType_Ready(&StdoutType) < 0) return 0; m = PyModule_Create(&stdcallbkmodule); if (m) { Py_INCREF(&StdoutType); PyModule_AddObject(m, "Stdout", (PyObject*) &StdoutType); fputs("PyModule_AddObject() Called\n", fp); fflush(fp); } g_stdout = StdoutType.tp_new(&StdoutType, 0, 0); /*PySys_SetObject("stdout", g_stdout)*/ fprintf(fp, "PySys_SetObject(stdout) returned %d\n", PySys_SetObject("stdout", g_stdout)); fflush(fp); /*PySys_SetObject("stderr", g_stdout)*/ fprintf(fp, "PySys_SetObject(stderr) returned %d\n", PySys_SetObject("stderr", g_stdout)); fflush(fp); return m; } /* called by cpp exe _after_ Py_Initialize(); */ void __declspec(dllexport) import_stdcallbk(void) { PyImport_ImportModule("stdcallbk"); } /* called by cpp exe _before_ Py_Initialize(); */ void __declspec(dllexport) register_callback(CALLBK_FUNC_T* callback) { PyImport_AppendInittab("stdcallbk", &PyInit_stdcallbk); callback_write_func = callback; } /* < /stdcallbk.pyd > */ /*------------- Embarcadero C++ Builder exe ---------------------*/ #include "/py_module/stdcallbk_module.h" void __stdcall callback_write_func(const char* p) { ShowMessage(p); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { PyObject *pName, *pModule; register_callback(callback_write_func); Py_Initialize(); import_stdcallbk(); //PyRun_SimpleString("import stdcallbk\n"); pName = PyUnicode_FromString("hello_emb.py"); pModule = PyImport_Import(pName); Py_Finalize(); } //--------------------------------------------------------------------------- -------------- python script - hello_emb.py ---------------- #import stdcallbk print("HELLO FRED !") assert 1==2 ------------------------------------------------------------ When run from the cpp exe, I get a messagebox "HELLO FRED!" followed by an empty message box which I assume is the carriage return. All good so far, but when the exception is raised, I get nothing. Nothing is written to the text file either. But... if I uncomment the "import stdcallbk" from the python script and run it from the command line, I get this: D:\projects\embed_python3\Win32\Debug>hello_emb.py ----HELLO FRED !-------- --------Traceback (most recent call last): -------- File "D:\projects\embed_python3\Win32\Debug\hello_emb.py", line 7, in <module> -------- --------assert 1==2-------- --------AssertionError---------------- ---- and this: D:\projects\embed_python3\Win32\Debug>type debuggered.txt got to here Vers 12 PyModule_AddObject() Called PySys_SetObject(stdout) returned 0 PySys_SetObject(stderr) returned 0 HELLO FRED ! Traceback (most recent call last): File "D:\projects\embed_python3\Win32\Debug\hello_emb.py", line 7, in <module> assert 1==2 AssertionError So it DOES work, just not when it is run from the cpp exe. Anybody have any idea what on earth is going on here? Cheers -- http://mail.python.org/mailman/listinfo/python-list
|