问题描述
请考虑以下代码,这些代码从C ++运行嵌入式Python脚本。它创建了一个嵌入式python模块,其功能是在执行时报告当前文件/行。
#include <Python.h>
#include <iostream>
#include <fstream>
PyObject * mymodule_meth_test(PyObject * self) {
PyTraceBack_Here(PyEval_GetFrame());
PyObject * exc;
PyObject * val;
PyObject * tb;
PyErr_Fetch(&exc,&val,&tb);
PyTraceBack_Print(tb,PySys_Getobject("stderr"));
std::cout << "LINE is " << PyLong_AsLong(PyObject_GetAttrString(PyObject_GetAttrString(tb,"tb_frame"),"f_lineno")) << std::endl;
std::cout << "FILE is " << PyUnicode_AsUTF8(PyObject_GetAttrString(PyObject_GetAttrString(PyObject_GetAttrString(tb,"f_code"),"co_filename")) << std::endl;
Py_RETURN_NONE;
}
PyMethodDef module_methods[] = {
{"test",(PyCFunction)mymodule_meth_test,METH_NOARGS,NULL},{},};
PyModuleDef module_def = {PyModuleDef_HEAD_INIT,"mymodule",NULL,-1,module_methods};
extern "C" PyObject * PyInit_mymodule() {
PyObject * module = PyModule_Create(&module_def);
return module;
}
void runScript( const std::string& script,bool utf8 )
{
Py_SetPythonHome( L"C:\\dev\\vobs_sde\\sde\\3rdparty\\tools_ext\\python\\python38" );
PyImport_AppendInittab("mymodule",&PyInit_mymodule);
// Initialize the Python Interpreter
Py_Initialize();
FILE* file = NULL;
open(&file,script);
if ( file )
{
wchar_t* sScriptUTF8 = Py_DecodeLocale(script.c_str(),NULL);
if ( PyRun_SimpleFile(file,(utf8) ? (const char*) sScriptUTF8 : script.c_str()) == 0 )
std::cout << "SUCCESS" << std::endl;
else
std::cout << "FAIL" << std::endl;
fclose(file);
}
Py_Finalize();
}
int main( int argc,char* argv[] )
{
std::fstream file2;
file2.open( "mainéfile.py",std::ios_base::out );
file2 << "import mymodule" << std::endl;
file2 << "mymodule.test()" << std::endl;
file2.close();
std::cout << std::endl << "Will fail to execute script" << std::endl;
runScript( "mainéfile.py",false );
std::cout << std::endl << "Will work! But FILE will be reported as 'm' instead of 'mainéfile.py'" << std::endl;
runScript( "mainéfile.py",true );
return 0;
}
此脚本输出:
Will fail to execute script
FAIL
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 4: invalid continuation byte
Will work! But FILE will be reported as 'm' instead of 'mainéfile.py'
Traceback (most recent call last):
File "m",line 2,in <module>
LINE is 2
FILE is m
SUCCESS
因此,如您所见:
- 如果我将常规
char*
“mainéfile.py”传递给PyRun_SimpleFile
,它将无法运行脚本。 - 如果我将
wchar_t
“mainéfile.py”字符串传递给PyRun_SimpleFile
,它可以运行脚本,但是mymodule_meth_test
报告的文件名是m
而预计mainéfile.py
。
这很可能是因为,像wchar_t
一样,“mainéfile.py”是“'m',0,'a',0,...”,后来被解释为常规{{1} }变成“ m”,因为第二项被认为是EOS。
如何调用char*
才能正常工作?
注意,我最终可以按以下方式致电PyRun_SimpleFile
:
PyRun_SimpleFile
但是,稍后在std::string utf8Str = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(Py_DecodeLocale(script.c_str(),NULL));
if ( PyRun_SimpleFile(file,utf8Str.c_str()) == 0 )
std::cout << "SUCCESS" << std::endl;
else
std::cout << "FAIL" << std::endl;
中对mymodule_meth_test
的调用将返回PyUnicode_AsUTF8
,但我找不到如何正确检索文件名的方法。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)