Newbee!!BPL question! Printing to standard output

Alex Martelli aleaxit at yahoo.com
Mon Jan 22 05:39:50 EST 2001


"Khaled Khairy" <khairy at magnet.fsu.edu> wrote in message
news:3A6B8C21.ADEAB05E at magnet.fsu.edu...
    [snip]
> I'm using the Boost Python Library to use Python as an interface for a C++
> library. Boost does an excellent job.
> What I would like to be able to do is get a handle to the intepreter
> terminal inside my C++ code, and directly print from
> there, not through returning a string on an exported function.

In the bare C API, you have several choices -- I'm not quite
sure which ones are wrapped, and at what level, by Boost Python
(I have not done 'printing' from inside a BPL-written extension).

The simplest way, if the string you want to print is in your
std::string variable named Foo and it contains no quotes &c:

void printIt1(const std::string& Foo)
{
    std::string temp = std::string("print \"") + Foo + "\"";
    PyRun_SimpleString(temp.c_str());
}

More elaborate ways proceed by getting at the sys module,
obtaining its attribute stdout, and calling method 'write'
on said stdout (or slight variants on this).  Nothing too
terrible, mind you... for example, again with the C API:

void printIt2(const std::string& Foo)
{
    PyObject* pSys = PyImport_ImportModule("sys");
    PyObject* pStdout = PyObject_GetAttrString(pSys, "stdout");
    PyObject* pResult = PyObject_CallMethod(pStdout, "write",
        "%s", Foo.c_str());
    Py_DECREF(pResult);
    Py_DECREF(pStdout);
    Py_DECREF(pSys);
}

You can no doubt remove the explicit reference-decrements
here by making use of the smart pointers/references that BPL
gives you, but that's just a minor (if useful) convenience.

Also, obviously, you may want to do the import-module and
get-attribute only once, rather than for each 'print', by
saving pStdout (or the bound-method-reference pointer, if
you prefer) somewhere in your state; however, while a little
bit faster, that will give you problem adjusting your output
if the Python side ever sets something different for a while
as the value of sys.stdout -- your output would keep going
to the 'OLD' stdout (the one that was set when you did the
get-attribute initialization); I think that doing the three
calls each time may be simplest for most uses (and the little
overhead is probably not a biggie compared with the overhead
of formatting and I/O, anyway).

Lastly, it's also (almost) trivial to wrap this up as a C++
stream buffer if you want; but the added-value is small
unless you need to output polymorphically to "the Python
standard output" OR other C++ output streams.


Alex






More information about the Python-list mailing list