Python-3-输出重定向使用CC
Python 3 输出重定向使用C/C++
Python 3 **输出重定向使用
C/C++**
By:gddsky
目标
希望将
Python 3
的输出重定向到自定义的输出目标。
核心
Python
使用
sys.stdout
、
sys.stderr
做输出目标,只要我们替换这两个值就可以重定向到我们自定义目标。替换的值的规则在
Python
的文档中
sys (module)
的
sys.stdout
上面说明只要添加一个
write
函数就可以了。像这样:
write(self, str)
我们只要在这个函数里面调用我们自己的输出函数就可以实现该目标了。
方案
在
C++
中写一个
Python
模块,并导入
在
C++
中利用
PyRun_SimpleString
建立一个
PyObject
去替换原始的
sys.stdout
、
sys.stderr
搞定!!!
代码
模块定义部分代码(用
python demo
下的例子改写的)
static
PyObject * console_write ( PyObject * self , PyObject * args )
{
if ( s_pyConsoleNotify != NULL )
{
const
char * pMsgString =0;
if (! PyArg_ParseTuple ( args , “s” , & pMsgString ))
{
return
NULL ;
}
//
我们自己的输出函数
myprint(pMsgString);
}
Py_INCREF ( Py_None );
return
Py_None ;
}
static
PyMethodDef
console_methods [] = {
{
“test” ,
console_test ,
METH_NOARGS , “Return the meaning of everything.” },
{
“write” ,
console_write ,
METH_VARARGS , NULL },
{
NULL ,
NULL }
/* sentinel */
};
static
struct
PyModuleDef
consolemodule = {
{}, /* m_base */
“console_capi” ,
/* m_name */
0,
/* m_doc */
0,
/* m_size */
console_methods ,
/* m_methods */
0,
/* m_reload */
0,
/* m_traverse */
0,
/* m_clear */
0,
/* m_free */
};
PyObject
PyInit_console ( void )
{
return
PyModule_Create (& consolemodule );
}
用
C++
执行的
Python
代码
void myOutput()
{
PyImport_AppendInittab ( “console_capi” , PyInit_console );
Py_Initialize ();
PyRun_SimpleString (
“import sys/n”
“import console_capi/n”
“class XConsole:/n”
"
def write(self, s):/n"
"
console_capi.write(s)/n"
//
这里将输出信息转给 console_write 函数
“myconsole = XConsole()/n”
“sys.stdout = myconsole/n”
“sys.stderr = myconsole”
);
}
经验
用 PyArg_ParseTuple 函数做参数解析,怎么都是错误的,最后才发现原来是因为 python 的脚本里面写的 console_capi.write(
self
, s)
,以为 console_write
( PyObject * self , PyObject * args )
的 self 就是由脚本中的这个 self 传进来了,结果这个 self 与脚本的 self 不一样,它是 module 的 PyObject ,将 console_capi.write(
self
, s)
改成 console_capi.write(s) 之后,解析就对了。
在 C++ 中,可以看 PyObject 结构,里面有一个 ob_type.tp_name 的值,它直接显示这个 Object 是什么类型,比如说 module 、 str 、 tuple ,这个值让我们可以很方便的得到这个 Object 的类型,调试比较方便。
一些问题实在麻烦,可以考虑直接下 source 版本编译 Debug 来调试,有些问题处理还是比较方便。