client/ScriptLib/PythonLauncher.cpp

282 lines
5.3 KiB
C++

#include "StdAfx.h"
#include "../eterPack/EterPackManager.h"
#include "PythonLauncher.h"
CPythonLauncher::CPythonLauncher()
{
Py_Initialize();
}
CPythonLauncher::~CPythonLauncher()
{
Clear();
}
void CPythonLauncher::Clear()
{
Py_Finalize();
}
std::string g_stTraceBuffer[512];
int g_nCurTraceN = 0;
void Traceback()
{
std::string str;
for (int i = 0; i < g_nCurTraceN; ++i)
{
str.append(g_stTraceBuffer[i]);
str.append("\n");
}
PyObject * exc;
PyObject * v;
PyObject * tb;
const char * errStr;
PyErr_Fetch(&exc, &v, &tb);
if (PyString_Check(v))
{
errStr = PyString_AS_STRING(v);
str.append("Error: ");
str.append(errStr);
Tracef("%s\n", errStr);
}
Py_DECREF(exc);
Py_DECREF(v);
Py_DECREF(tb);
LogBoxf("Traceback:\n\n%s\n", str.c_str());
}
int TraceFunc(PyObject * obj, PyFrameObject * f, int what, PyObject *arg)
{
const char * funcname;
char szTraceBuffer[128];
switch (what)
{
case PyTrace_CALL:
if (g_nCurTraceN >= 512)
return 0;
if (Py_OptimizeFlag)
f->f_lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
funcname = PyString_AsString(f->f_code->co_name);
_snprintf(szTraceBuffer, sizeof(szTraceBuffer), "Call: File \"%s\", line %d, in %s",
PyString_AsString(f->f_code->co_filename),
f->f_lineno,
funcname);
g_stTraceBuffer[g_nCurTraceN++]=szTraceBuffer;
break;
case PyTrace_RETURN:
if (g_nCurTraceN > 0)
--g_nCurTraceN;
break;
case PyTrace_EXCEPTION:
if (g_nCurTraceN >= 512)
return 0;
PyObject * exc_type, * exc_value, * exc_traceback;
PyTuple_GetObject(arg, 0, &exc_type);
PyTuple_GetObject(arg, 1, &exc_value);
PyTuple_GetObject(arg, 2, &exc_traceback);
int len;
const char * exc_str;
PyObject_AsCharBuffer(exc_type, &exc_str, &len);
_snprintf(szTraceBuffer, sizeof(szTraceBuffer), "Exception: File \"%s\", line %d, in %s",
PyString_AS_STRING(f->f_code->co_filename),
f->f_lineno,
PyString_AS_STRING(f->f_code->co_name));
g_stTraceBuffer[g_nCurTraceN++]=szTraceBuffer;
break;
}
return 0;
}
void CPythonLauncher::SetTraceFunc(int (*pFunc)(PyObject * obj, PyFrameObject * f, int what, PyObject *arg))
{
PyEval_SetTrace(pFunc, NULL);
}
bool CPythonLauncher::Create(const char* c_szProgramName)
{
NANOBEGIN
Py_SetProgramName((char*)c_szProgramName);
#ifdef _DEBUG
PyEval_SetTrace(TraceFunc, NULL);
#endif
m_poModule = PyImport_AddModule((char *) "__main__");
if (!m_poModule)
return false;
m_poDic = PyModule_GetDict(m_poModule);
PyObject * builtins = PyImport_ImportModule("__builtin__");
PyModule_AddIntConstant(builtins, "TRUE", 1);
PyModule_AddIntConstant(builtins, "FALSE", 0);
PyDict_SetItemString(m_poDic, "__builtins__", builtins);
Py_DECREF(builtins);
if (!RunLine("import __main__"))
return false;
if (!RunLine("import sys"))
return false;
NANOEND
return true;
}
bool CPythonLauncher::RunCompiledFile(const char* c_szFileName)
{
NANOBEGIN
FILE * fp = fopen(c_szFileName, "rb");
if (!fp)
return false;
PyCodeObject *co;
PyObject *v;
long magic;
long PyImport_GetMagicNumber(void);
magic = _PyMarshal_ReadLongFromFile(fp);
if (magic != PyImport_GetMagicNumber())
{
PyErr_SetString(PyExc_RuntimeError, "Bad magic number in .pyc file");
fclose(fp);
return false;
}
_PyMarshal_ReadLongFromFile(fp);
v = _PyMarshal_ReadLastObjectFromFile(fp);
fclose(fp);
if (!v || !PyCode_Check(v))
{
Py_XDECREF(v);
PyErr_SetString(PyExc_RuntimeError, "Bad code object in .pyc file");
return false;
}
co = (PyCodeObject *) v;
v = PyEval_EvalCode(co, m_poDic, m_poDic);
/* if (v && flags)
flags->cf_flags |= (co->co_flags & PyCF_MASK);*/
Py_DECREF(co);
if (!v)
{
Traceback();
return false;
}
Py_DECREF(v);
if (Py_FlushLine())
PyErr_Clear();
NANOEND
return true;
}
bool CPythonLauncher::RunMemoryTextFile(const char* c_szFileName, UINT uFileSize, const VOID* c_pvFileData)
{
NANOBEGIN
const CHAR* c_pcFileData=(const CHAR*)c_pvFileData;
std::string stConvFileData;
stConvFileData.reserve(uFileSize);
stConvFileData+="exec(compile('''";
// ConvertPythonTextFormat
{
for (UINT i=0; i<uFileSize; ++i)
{
if (c_pcFileData[i]!=13)
stConvFileData+=c_pcFileData[i];
}
}
stConvFileData+= "''', ";
stConvFileData+= "'";
stConvFileData+= c_szFileName;
stConvFileData+= "', ";
stConvFileData+= "'exec'))";
const CHAR* c_pcConvFileData=stConvFileData.c_str();
NANOEND
return RunLine(c_pcConvFileData);
}
bool CPythonLauncher::RunFile(const char* c_szFileName)
{
char* acBufData=NULL;
DWORD dwBufSize=0;
{
CMappedFile file;
const VOID* pvData;
CEterPackManager::Instance().Get(file, c_szFileName, &pvData);
dwBufSize=file.Size();
if (dwBufSize==0)
return false;
acBufData=new char[dwBufSize];
memcpy(acBufData, pvData, dwBufSize);
}
bool ret=false;
ret=RunMemoryTextFile(c_szFileName, dwBufSize, acBufData);
delete [] acBufData;
return ret;
}
bool CPythonLauncher::RunLine(const char* c_szSrc)
{
PyObject * v = PyRun_String((char *) c_szSrc, Py_file_input, m_poDic, m_poDic);
if (!v)
{
Traceback();
return false;
}
Py_DECREF(v);
return true;
}
const char* CPythonLauncher::GetError()
{
PyObject* exc;
PyObject* v;
PyObject* tb;
PyErr_Fetch(&exc, &v, &tb);
if (PyString_Check(v))
return PyString_AS_STRING(v);
return "";
}