PyImport_Import problems with a BOOST_PYTHON_MODULE defined module
Thanks to some previous answers plus some intense googling, I've been able to use a C++ class to capture stdout and stderr. However, I have encountered a problem with PyImport_Import and a module defined with BOOST_PYTHON_MODULE. I created a StdoutCatcher C++ class (in a module named RuntimeSupport) and have got to the point where I can use it from within Python ok:
import sys, RuntimeSupport sys.stdout = RuntimeSupport.StdoutCatcher() sys.stderr = RuntimeSupport.StdoutCatcher()
But my goal is to redirect stdout purely using the C APIs, but I still have much to learn and have hit a bit of a wall after experimenting all day. I found that PyImport_Import should accomplish what I want, but for all my experimenting I just can't get it to work. Below is the code and it would be great if anyone could critique my use of boost.python and the Python C API, and point out where I have gone wrong. All criticism would be very much appreciated. Building with MS VC++ 6 on w2k, using Python embedded in the app. //********************************************************* class StdoutCatcher { public: StdoutCatcher() { clear(); } void write( const std::string& str ) { text_ += str; } static const std::string& text(void) { return text_; } static void clear(void) { text_.erase(); } private: static std::string text_; }; std::string StdoutCatcher::text_; //********************************************************* // Python module BOOST_PYTHON_MODULE(RuntimeSupport) { class_<StdoutCatcher>("StdoutCatcher") .def( "write", &StdoutCatcher::write ) ; } ... initialize everything ... PyImport_AppendInittab("RuntimeSupport", initRuntimeSupport); Py_Initialize(); mainModule_ = new object(handle<>(borrowed( PyImport_AddModule("__main__") ) ) ); mainNamespace_ = new dict(mainModule_->attr("__dict__") ); ... everything now works ok if just using Python ... but I can't get it to work using just API calls, ... see below // import the RuntimeSupport module // --> I tried all import ways; // PyImport_ImportModuleEx, PyImport_Import, // PyImport_ImportModule boost::python::str supportModuleName("RuntimeSupport"); handle<> supportModule( PyImport_Import(supportModuleName.ptr()) ); // create an instance of StdoutCatcher // --> this bit doesn't work and returns NoneType // --> maybe because PyImport failed? object catcher = mainNamespace_->get("StdoutCatcher"); // --> is there a better way to check for NoneType // than a strcmp? PyObject* pObj = catcher.ptr(); if ( strcmp(pObj->ob_type->tp_name, "NoneType") == 0) { // ... why isn't StdoutCatcher being found? } else { // --> never get to this bit // create an instance of StdoutCatcher object catcherObj = catcher(); // set sys.stdout and sys.stderr to the // StdoutCatcher instance PySys_SetObject("stdout",catcherObj.ptr()); PySys_SetObject("stderr",catcherObj.ptr()); } ... so the main question is, why can't I import StdoutCatcher using the APIs? Thanks, Peter
participants (1)
-
Peter