See More

#include "ffpython.h" using namespace ff; std::vector FFPython::m_regFuncs; std::map FFPython::m_allocObjs; PyObject* FFPython::pyobjBuildTmpObj = NULL; static PyObject* callExt(PyObject* self, PyObject* args) { size_t idFunc = 0; int64_t addrObj = 0; int nOps = 0; int nAutoRelease = 0; PyObject* pyArgList = NULL; if (!PyArg_ParseTuple(args, "LiO|ii", &addrObj, &idFunc, &pyArgList, &nOps, &nAutoRelease) || pyArgList == NULL) return NULL; ScriptIterface* pfunc = FFPython::getRegFuncByID(idFunc); if (!pfunc) { Py_RETURN_NONE; } pfunc->clearTmpArg();//!Ö§³ÖµÝ¹é pfunc->pobjArg = (void*)addrObj;//!Èç¹ûÊÇÀà·½·¨£¬ÐèÒªÓÐÀàÖ¸Õë²ÎÊý ScriptCppOps<:vector> >::scriptToCpp(pyArgList, pfunc->tmpArgs); if (nOps != E_CLASS_DEL && pfunc->tmpArgs.size() < pfunc->nMinArgs) { char buff[256] = { 0 }; SAFE_SPRINTF(buff, sizeof(buff), "args num error func:%s, expect:%d, given:%d", pfunc->strName.c_str(), pfunc->nMinArgs, (int)pfunc->tmpArgs.size()); PyErr_SetString(PyExc_TypeError, buff); pfunc->clearTmpArg(); return NULL; } PyObject* ret = NULL; if (nOps == E_STATIC_FUNC) { ret = pfunc->handleRun(); } else if (nOps == E_CLASS_NEW) { void* pObjNew = pfunc->handleNew(); FFPython::m_allocObjs[pObjNew] = pfunc; ret = ScriptCppOps::scriptFromCpp(pObjNew); } else if (nOps == E_CLASS_DEL) { std::map::iterator it = FFPython::m_allocObjs.find(pfunc->pobjArg); if (it != FFPython::m_allocObjs.end()) { FFPython::m_allocObjs.erase(it); pfunc->handleDel(); } } else if (nOps == E_CLASS_METHOD || nOps == E_CLASS_FIELD) { if (nAutoRelease)//!Èç¹ûÊÇpython´´½¨µÄ¶ÔÏó£¬ÑéÖ¤Ò»ÏÂÖ¸ÕëÓÐЧÐÔ { std::map::iterator it = FFPython::m_allocObjs.find(pfunc->pobjArg); if (it == FFPython::m_allocObjs.end()) { Py_RETURN_NONE; } } ret = pfunc->handleRun(); } pfunc->clearTmpArg(); if (nOps == 2) Py_RETURN_NONE; return ret; } static PyMethodDef EmbMethods[] = { {"callExt", callExt, METH_VARARGS, "ffpython internal func"}, {NULL, NULL, 0, NULL} }; FFPython::FFPython() { #ifdef PYTHON_3 if (Py_IsInitialized()) { return; } struct PyInitTmpTool { static PyObject* PyInit_emb(void) { static PyModuleDef EmbModule = { PyModuleDef_HEAD_INIT, "ffpython", NULL, -1, EmbMethods, NULL, NULL, NULL, NULL }; return PyModule_Create(&EmbModule); } }; PyImport_AppendInittab("ffpython", &PyInitTmpTool::PyInit_emb); Py_Initialize(); #else Py_Initialize(); Py_InitModule3("ffpython", EmbMethods, ""); #endif addPath("./"); runCode("import ffpython"); { const char* strCode = "\ def regFuncExt(idFunc, name): \n\ import ffpython \n\ callCppFunc = ffpython.callExt \n\ def funReal(*args): \n\ return callCppFunc(0, idFunc, args, 0) \n\ setattr(ffpython, name, funReal) \n\ return True \n\ ffpython.regFuncExt = regFuncExt \n\ "; runCode(strCode); } { const char* strCode = "\ def regMethodExt(idFunc, name, nameClass) : \n\ import ffpython \n\ classType = getattr(ffpython, nameClass, None) \n\ if not classType: \n\ return False \n\ callCppFunc = ffpython.callExt \n\ def funReal(self, *args): \n\ return callCppFunc(self._cppInterObj_, idFunc, args, 0, self._autoRelease_) \n\ setattr(classType, name, funReal) \n\ return True \n\ ffpython.regMethodExt = regMethodExt \n\ "; runCode(strCode); } { const char* strCode = "\ def regFieldExt(nFuncID, fieldName, className): \n\ classType = getattr(ffpython, className, None) \n\ callExt = ffpython.callExt \n\ def getFieldVal(self) : \n\ return callExt(self._cppInterObj_, nFuncID, (), 4) \n\ def setFieldVal(self, value) : \n\ return callExt(self._cppInterObj_, nFuncID, (value,), 4) \n\ setattr(classType, fieldName, property(getFieldVal, setFieldVal))#add property \n\ return \n\ ffpython.regFieldExt = regFieldExt \n\ "; runCode(strCode); } { const char* strCode = "\ def buildTmpObj(className, ptr) : \n\ srcType = getattr(ffpython, className, None)\n\ if srcType : \n\ return srcType(cppTmpPtr = ptr) \n\ return None \n\ ffpython.buildTmpObj = buildTmpObj \n\ "; runCode(strCode); } FFPython::pyobjBuildTmpObj = getScriptVar("ffpython", "buildTmpObj"); } FFPython::~FFPython() { Py_XDECREF(pyobjBuildTmpObj); pyobjBuildTmpObj = NULL; for (size_t i = 0; i < m_regFuncs.size(); ++i) { delete m_regFuncs[i]; } m_regFuncs.clear(); for (size_t i = 0; i < m_listGlobalCache.size(); ++i) { Py_XDECREF(m_listGlobalCache[i]); } m_listGlobalCache.clear(); if (Py_IsInitialized()) Py_Finalize(); } void FFPython::addPath(const std::string& path) { char buff[1024]; SAFE_SPRINTF(buff, sizeof(buff), "import sys\nif '%s' not in sys.path:\n\tsys.path.append('%s')\n", path.c_str(), path.c_str()); runCode(buff); } void FFPython::runCode(const std::string& code) { PyRun_SimpleString(code.c_str()); if (PyErr_Occurred()) { traceback(m_strErr); } } PyObject* FFPython::callFuncByObj(PyObject* pFunc, std::vector& objArgs) { PyObject* pValue = NULL; if (pFunc && PyCallable_Check(pFunc)) { PyObject* pArgs = PyTuple_New(objArgs.size()); for (int i = 0; i < objArgs.size(); ++i) { PyTuple_SetItem(pArgs, i, objArgs[i]); } objArgs.clear(); pValue = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); } else { for (int i = 0; i < objArgs.size(); ++i) { Py_DECREF(objArgs[i]); } objArgs.clear(); } if (PyErr_Occurred()) { traceback(m_strErr); } if (!pValue) Py_RETURN_FALSE; return pValue; } PyObject* FFPython::getScriptVarByObj(PyObject* pModule, const std::string& strVarName) { PyObject* pValue = PyObject_GetAttrString(pModule, strVarName.c_str()); if (!pValue) { Py_RETURN_NONE; } return pValue; } PyObject* FFPython::getScriptVar(const std::string& strMod, const std::string& strVarName) { PyObject* pName = PyString_FromString(strMod.c_str()); if (!pName) Py_RETURN_FALSE; PyObject* pModule = PyImport_Import(pName); Py_DECREF(pName); if (!pModule) { Py_RETURN_NONE; } PyObject* pValue = getScriptVarByObj(pModule, strVarName); Py_DECREF(pModule); return pValue; } PyObject* FFPython::callFunc(const std::string& modName, const std::string& funcName, std::vector& objArgs) { PyObject* pFunc = getScriptVar(modName, funcName); PyObject* pValue = callFuncByObj(pFunc, objArgs); Py_XDECREF(pFunc); if (!pValue) Py_RETURN_FALSE; return pValue; } FFPython& FFPython::reg(ScriptIterface* pObj, const std::string& name, int nOps, std::string nameClass, std::string nameInherit) { FFPython::m_regFuncs.push_back(pObj); FFPython::m_regFuncs.back()->strName = name; if (nOps == E_STATIC_FUNC) { call("ffpython", "regFuncExt", FFPython::m_regFuncs.size() - 1, name); } else if (nOps == E_CLASS_NEW) { m_curRegClassName = nameClass; int idFunc = (int)FFPython::m_regFuncs.size() - 1; std::string strBaseInit; if (nameInherit.empty() == false) { nameInherit = std::string("(") + nameInherit + ")"; strBaseInit = nameInherit + ".__init__(self,cppTmpPtr=1)"; } char buff[1024*2]; SAFE_SPRINTF(buff, sizeof(buff), "\ class %s%s: \n\ def __init__(self, *args, **opt) : \n\ %s \n\ self._autoRelease_ = 0 \n\ self._cppInterObj_ = opt.get('cppTmpPtr', 0) \n\ if not self._cppInterObj_ : \n\ self._cppInterObj_ = ffpython.callExt(0, %d, args, 1) \n\ self._autoRelease_ = 1 \n\ def __del__(self) : \n\ if self._autoRelease_ : \n\ ffpython.callExt(self._cppInterObj_, %d, (), 2) \n\ def __repr__(self): \n\ return ''%%(self._cppInterObj_) \n\ def __str__(self): \n\ return ''%%(self._cppInterObj_) \n\ ffpython.%s = %s \n\ ", nameClass.c_str(), nameInherit.c_str(), strBaseInit.c_str(), idFunc, idFunc, nameClass.c_str(), nameClass.c_str(), nameClass.c_str(), nameClass.c_str()); runCode(buff); } else if (nOps == E_CLASS_METHOD) { if (nameClass.empty()) nameClass = m_curRegClassName; FFPython::m_regFuncs.back()->strName = nameClass + "." + name; call("ffpython", "regMethodExt", FFPython::m_regFuncs.size() - 1, name, nameClass); } else if (nOps == E_CLASS_FIELD) { if (nameClass.empty()) nameClass = m_curRegClassName; FFPython::m_regFuncs.back()->strName = nameClass + "." + name; call("ffpython", "regFieldExt", FFPython::m_regFuncs.size() - 1, name, nameClass); } return *this; } int FFPython::traceback(std::string& ret_) { ret_.clear(); PyObject* err = PyErr_Occurred(); if (!err) { return 0; } PyObject* ptype = NULL, * pvalue = NULL, * ptraceback = NULL; PyObject* pyth_module = NULL, * pyth_func = NULL; PyErr_Fetch(&ptype, &pvalue, &ptraceback); if (pvalue) { if (true == PyList_Check(pvalue)) { int64_t n = PyList_Size(pvalue); for (int64_t i = 0; i < n; ++i) { PyObject* pystr = PyObject_Str(PyList_GetItem(pvalue, i)); ret_ += PyString_AsString(pystr); ret_ += "\n"; Py_DECREF(pystr); } } else if (true == PyTuple_Check(pvalue)) { int64_t n = PyTuple_Size(pvalue); for (int64_t i = 0; i < n; ++i) { PyObject* tmp_str = PyTuple_GetItem(pvalue, i); if (true == PyTuple_Check(tmp_str)) { int64_t m = PyTuple_Size(tmp_str); for (int64_t j = 0; j < m; ++j) { PyObject* pystr = PyObject_Str(PyTuple_GetItem(tmp_str, j)); ret_ += PyString_AsString(pystr); ret_ += ","; Py_DECREF(pystr); } } else { PyObject* pystr = PyObject_Str(tmp_str); ret_ += PyString_AsString(pystr); Py_DECREF(pystr); } ret_ += "\n"; } } else { PyObject* pystr = PyObject_Str(pvalue); if (pystr) { ret_ += PyString_AsString(pystr); ret_ += "\n"; Py_DECREF(pystr); } } } /* See if we can get a full traceback */ PyObject* module_name = PyString_FromString("traceback"); pyth_module = PyImport_Import(module_name); Py_DECREF(module_name); if (pyth_module && ptype && pvalue && ptraceback) { pyth_func = PyObject_GetAttrString(pyth_module, "format_tb"); if (pyth_func && PyCallable_Check(pyth_func)) { PyObject* pArgs = PyTuple_New(1); PyTuple_SetItem(pArgs, 0, ptraceback); PyObject* pyth_val = PyObject_CallObject(pyth_func, pArgs); if (pyth_val && true == PyList_Check(pyth_val)) { int64_t n = PyList_Size(pyth_val); for (int64_t i = 0; i < n; ++i) { PyObject* tmp_str = PyList_GetItem(pyth_val, i); PyObject* pystr = PyObject_Str(tmp_str); if (pystr) { ret_ += PyString_AsString(pystr); Py_DECREF(pystr); } ret_ += "\n"; } } else { PyErr_Print(); } Py_XDECREF(pArgs); Py_XDECREF(pyth_val); } } Py_XDECREF(pyth_func); Py_XDECREF(pyth_module); Py_XDECREF(ptype); Py_XDECREF(pvalue); Py_XDECREF(ptraceback); PyErr_Clear(); printf("ffpython traceback:%s\n", ret_.c_str()); return 0; } bool FFPython::reload(const std::string& py_name_) { PyObject* pName = NULL, * pModule = NULL; pName = PyString_FromString(py_name_.c_str()); pModule = PyImport_Import(pName); Py_DECREF(pName); if (NULL == pModule) { traceback(m_strErr); return false; } PyObject* pNewMod = PyImport_ReloadModule(pModule); Py_DECREF(pModule); if (NULL == pNewMod) { traceback(m_strErr); return false; } Py_DECREF(pNewMod); return 0; } bool FFPython::load(const std::string& py_name_) { PyObject* pName = NULL, * pModule = NULL; pName = PyString_FromString(py_name_.c_str()); pModule = PyImport_Import(pName); Py_DECREF(pName); if (NULL == pModule) { traceback(m_strErr); return false; } Py_DECREF(pModule); return 0; }