The amazing disappearing stderr

Peter Faulks faulksp at iinet.net.au
Wed May 2 05:24:46 EDT 2012


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







More information about the Python-list mailing list