[C++-sig] PyImport_Import problems with a BOOST_PYTHON_MODULE defined module

Peter python at cityofdreams.com
Thu Sep 2 05:46:16 CEST 2004


I solved  the initial import problem by defining a global object
variable and constructing an instance from that, i.e.,

object g_Catcher;

BOOST_PYTHON_MODULE(RuntimeSupport)
{
    g_Catcher =
        class_<StdoutCatcher>("StdoutCatcher")
            .def( "write", &StdoutCatcher::write )
            ;
}

Then imported the module and created the class instance:

  boost::python::str supportModuleName("RuntimeSupport");
  handle<> supportModule(
           PyImport_Import(supportModuleName.ptr()) );

  object catcherObj = g_Catcher();

  PySys_SetObject("stdout",catcherObj.ptr());
  PySys_SetObject("stderr",catcherObj.ptr());


I'm still having problems with the visibility of modules imported
PyImport_Import.  Python code still does not see these modules, so I
have to reimport them in Python.

Regards
Peter


> 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
> 
> 
> 
> 
> 
> _______________________________________________
> C++-sig mailing list
> C++-sig at python.org
> http://mail.python.org/mailman/listinfo/c++-sig
> 
> 





More information about the Cplusplus-sig mailing list