I wish I had found a better way, but this way seems to work, (will update if I find a better solution):
If you defined a class in Python to catch sys.stdout
writes:
import sys
class CatchOutErr:
def __init__(self):
self.value = ''
def write(self, txt):
self.value += txt
catchOutErr = CatchOutErr()
sys.stdout = catchOutErr
sys.stderr = catchOutErr
And you passed the value received from this handler to C++, converted to string, etc...
#include <Python.h>
#include <iostream>
#include <stdio.h>
int main(int argc, char *argv[])
{
Py_Initialize();
PyObject *pModule = PyImport_AddModule("__main__"); //create main module
std::string stdOutErr = "import sys\nclass CatchOutErr:\n\tdef __init__(self):\n\t\tself.value = ''\n\tdef write(self, txt):\n\t\tself.value += txt\ncatchOutErr = CatchOutErr()\nsys.stdout = catchOutErr\nsys.stderr = catchOutErr\n";
PyRun_SimpleString(stdOutErr.c_str()); //invoke code to redirect
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
PyObject *catcher = PyObject_GetAttrString(pModule, "catchOutErr"); //get our catchOutErr created above
PyObject *output = PyObject_GetAttrString(catcher,"value"); //get the stdout and stderr from our catchOutErr object
std::string s = PyString_AsString(output);
Py_DECREF(catcher);
Py_DECREF(output);
Py_DECREF(s);
std::cout << s;
return 0;
}
('Today is', 'Thu Jul 30 09:02:55 2020')
For Python3:
...
PyObject *output = PyObject_GetAttrString(catcher,"value"); //get the stdout and stderr from our catchOutErr object
PyObject *encodedData = PyUnicode_AsEncodedString(output, "ascii", NULL);
Py_DECREF(output);
Py_DECREF(encodedData);
char* buf;
Py_ssize_t len;
PyBytes_AsStringAndSize(encodedData, &buf, &len);
std::cout << std::string(buf) << std::endl;
Reference:
https://stackoverflow.com/a/4307737/9238288
https://cpp.hotexamples.com/examples/-/-/PyUnicode_AsEncodedString/cpp-pyunicode_asencodedstring-function-examples.html