在我的c ++程序中,我有一个名为“pEngine”的类,它应该处理我的程序和python会话之间的交互。可以有任意数量的这些pEngine,每个都需要单独工作,因为在初始化期间它们每个都执行不同的python脚本(直到运行时才知道)。
目前我有每个脚本定义一个主函数,它接受一个变量,有效负载,并根据脚本产生一个不同的输出,我的程序管道返回。然后删除pEngine。对于单个pEngine,我的代码工作得很好,允许我在函数的脚本中预加载数据,然后在需要时调用它。
我的问题是,由于它关闭了会话,所有其他pEngine都会受到影响。我无法将多个脚本加载到同一个会话中,因为它们的主要功能都有相同的原型。我正在寻找的是一种方法,让python会话实例对象是独立的和个体的,所以我可以对它运行命令。
我的pEngine.h
#include <cstring>
#include "Engine.h"
#include "/usr/include/python2.7/Python.h"
#ifndef PENGINE_H
#define PENGINE_H
class pEngine : public Engine
{
public:
pEngine();
~pEngine();
std::string execute(const std::string& cmd);
int setwd(const std::string& dir);
int source(const std::string& script);
std::string main(const std::string& payload);
private:
PyObject *pModule;
PyObject *stdOut;
};
#endif /* PENGINE_H */
我的pEngine.cpp
#include "pEngine.h"
pEngine::pEngine()
{
/* Start a python session and create a class to capture the standard out
text. Define it as the standard out location and run this code in the
session. Then store a pointer to this python object to extract returned
values. */
Py_Initialize();
pModule = PyImport_AddModule("__main__"); //create main module
std::stringstream pythonOutputs;
pythonOutputs << "import sys" << "\n"
<< "class CatchStdOut:" << "\n"
<< "\t" << "def __init__(self):" << "\n"
<< "\t" << "\t" << "self.value = ''" << "\n"
<< "\t" << "def write(self, txt):" << "\n"
<< "\t" << "\t" << "self.value += txt" << "\n"
<< "\t" << "def clear(self):" << "\n"
<< "\t" << "\t" << "self.value = ''" << "\n"
<< "StdOut = CatchStdOut()" << "\n"
<< "sys.stdout = StdOut";
PyRun_SimpleString((pythonOutputs.str()).c_str());
stdOut = PyObject_GetAttrString(pModule,"StdOut");
}
pEngine::~pEngine(){
Py_Finalize();
}
std::string pEngine::execute(const std::string& cmd)
{
/* Place cmd in try except statement to protect against unknown errors. */
std::stringstream pString;
pString << "program_status = 200" << "\n"
<< "StdOut.clear()" << "\n"
<< "try:" << "\n"
<< "\t" << cmd << "\n"
<< "except Exception as e:" << "\n"
<< "\t" << "program_status = 400" << "\n"
<< "\t" << "print(e)";
/* Run Command against the interpreter and store returned answer. */
PyRun_SimpleString( (pString.str()).c_str() );
PyErr_Print(); //make python print
//returned payload
std::string RPL =
PyString_AsString(PyObject_GetAttrString(stdOut,"value"));
/* Clear the payload from the capture object and run a command to fill in
the status. */
std::stringstream statusCollector;
statusCollector << "StdOut.clear()\n"
<< "print program_status";
/* Run command and extract status. */
PyRun_SimpleString( (statusCollector.str()).c_str() );
PyErr_Print();
//status
std::string PST =
PyString_AsString(PyObject_GetAttrString(stdOut,"value"));
if (!RPL.empty() && RPL[RPL.length()-1] == '\n') RPL.erase(RPL.length()-1);
if (!PST.empty() && PST[PST.length()-1] == '\n') PST.erase(PST.length()-1);
/* Set Program status and return the payload from the python session. */
program_status = std::stoi( PST );
return RPL;
}
std::string pEngine::main(const std::string& payload)
{
std::string returned = execute( "print main("+toEscapedString(payload)+")");
Py_Finalize();
if( program_status != 200 ) status = Engine::ENG_EXECUTE_ERROR;
return returned;
}
int pEngine::setwd(const std::string& dir)
{
std::string pString = "import os\n\tos.chdir(" + toEscapedString(dir) + ")";
execute( pString );
if( program_status != 200 ) status = Engine::ENG_SESSION_ERROR;
return status;
}
int pEngine::source(const std::string& script)
{
std::string pString = "execfile(" + toEscapedString(script) + ")";
execute( pString );
if( program_status != 200 ) status = Engine::ENG_SESSION_ERROR;
return status;
}