/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Additional permissions under GNU GPL version 3 section 7 If you modify this Program, or any covered work, by linking or combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK (or a modified version of those libraries), containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the licensors of this Program grant you additional permission to convey the resulting work. Corresponding Source for a non-source form of such a combination shall include the source code for the parts of OpenSSL and IJG JPEG Library used as well as that of the covered work. You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "hsTypes.h" #include "PythonInterface.h" #include "compile.h" #include "eval.h" #include "marshal.h" #include "cStringIO.h" static PyObject* stdFile; // python object of the stdout and err file void PythonInterface::initPython(std::string rootDir) { // if haven't been initialized then do it if ( Py_IsInitialized() == 0 ) { // initialize the Python stuff // let Python do some intialization... Py_SetProgramName("plasma"); Py_Initialize(); // intialize any of our special plasma python modules // initP2PInterface(); // save object to the Plasma module // plasmaMod = PyImport_ImportModule("Plasma"); // create the StringIO for the stdout and stderr file PycStringIO = (struct PycStringIO_CAPI*)PyCObject_Import("cStringIO", "cStringIO_CAPI"); stdFile = (*PycStringIO->NewOutput)(20000); // if we need the builtins then find the builtin module PyObject* sysmod = PyImport_ImportModule("sys"); // then add the builtin dicitionary to our module's dictionary if (sysmod != NULL ) { // get the sys's dictionary to find the stdout and stderr PyObject* sys_dict = PyModule_GetDict(sysmod); if (stdFile != nil) { PyDict_SetItemString(sys_dict,"stdout", stdFile); PyDict_SetItemString(sys_dict,"stderr", stdFile); } // NOTE: we will reset the path to not include paths // ...that Python may have found in the registery PyObject* path_list = PyList_New(0); printf("Setting up include dirs:\n"); printf("%s\n",rootDir.c_str()); PyObject* more_path = PyString_FromString(rootDir.c_str()); PyList_Append(path_list, more_path); // make sure that our plasma libraries are gotten before the system ones std::string temp = rootDir + "plasma"; printf("%s\n",temp.c_str()); PyObject* more_path3 = PyString_FromString(temp.c_str()); PyList_Append(path_list, more_path3); temp = rootDir + "system"; printf("%s\n\n",temp.c_str()); PyObject* more_path2 = PyString_FromString("system"); PyList_Append(path_list, more_path2); // set the path to be this one PyDict_SetItemString(sys_dict,"path",path_list); Py_DECREF(sysmod); } } // initialized++; } void PythonInterface::addPythonPath(std::string path) { PyObject* sysmod = PyImport_ImportModule("sys"); if (sysmod != NULL) { PyObject* sys_dict = PyModule_GetDict(sysmod); PyObject* path_list = PyDict_GetItemString(sys_dict, "path"); printf("Adding path %s\n", path.c_str()); PyObject* more_path = PyString_FromString(path.c_str()); PyList_Append(path_list, more_path); Py_DECREF(sysmod); } } void PythonInterface::finiPython() { if (Py_IsInitialized() != 0) { Py_Finalize(); } } ///////////////////////////////////////////////////////////////////////////// // // Function : CompileString // PARAMETERS : command - string of commands to execute in the... // : filename - filename to say where to code came from // // PURPOSE : run a python string in a specific module name // PyObject* PythonInterface::CompileString(char *command, char* filename) { PyObject* pycode = Py_CompileString(command, filename, Py_file_input); return pycode; } ///////////////////////////////////////////////////////////////////////////// // // Function : DumpObject // PARAMETERS : pyobject - string of commands to execute in the... // // PURPOSE : marshals an object into a char string // hsBool PythonInterface::DumpObject(PyObject* pyobj, char** pickle, Int32* size) { PyObject *s; // the python string object where the marsalled object wil go // convert object to a marshalled string python object s = PyMarshal_WriteObjectToString(pyobj); // did it actually do it? if ( s != NULL ) { // yes, then get the size and the string address *size = PyString_Size(s); *pickle = PyString_AsString(s); return true; } else // otherwise, there was an error { // Yikes! errors! PyErr_Print(); // FUTURE: we may have to get the string to display in max...later return false; } } ///////////////////////////////////////////////////////////////////////////// // // Function : getOutputAndReset // PARAMETERS : none // // PURPOSE : get the Output to the error file to be displayed // int PythonInterface::getOutputAndReset(char** line) { PyObject* pyStr = (*PycStringIO->cgetvalue)(stdFile); char *str = PyString_AsString( pyStr ); int size = PyString_Size( pyStr ); // reset the file back to zero PyObject_CallMethod(stdFile,"reset",""); /* // check to see if the debug python module is loaded if ( dbgOut != nil ) { // then send it the new text if ( PyObject_CallFunction(dbgOut,"s",str) == nil ) { // for some reason this function didn't, remember that and not call it again dbgOut = nil; // if there was an error make sure that the stderr gets flushed so it can be seen PyErr_Print(); // make sure the error is printed PyErr_Clear(); // clear the error } } */ if (line) *line = str; return size; } ///////////////////////////////////////////////////////////////////////////// // // Function : CreateModule // PARAMETERS : module - module name to create // // PURPOSE : create a new module with built-ins // PyObject* PythonInterface::CreateModule(char* module) { PyObject *m, *d; // first we must get rid of any old modules of the same name, we'll replace it PyObject *modules = PyImport_GetModuleDict(); if ((m = PyDict_GetItemString(modules, module)) != NULL && PyModule_Check(m)) // clear it _PyModule_Clear(m); // create the module m = PyImport_AddModule(module); if (m == NULL) return nil; d = PyModule_GetDict(m); // add in the built-ins // first make sure that we don't already have the builtins if (PyDict_GetItemString(d, "__builtins__") == NULL) { // if we need the builtins then find the builtin module PyObject *bimod = PyImport_ImportModule("__builtin__"); // then add the builtin dicitionary to our module's dictionary if (bimod == NULL || PyDict_SetItemString(d, "__builtins__", bimod) != 0) return nil; Py_DECREF(bimod); } return m; } ///////////////////////////////////////////////////////////////////////////// // // Function : RunPYC // PARAMETERS : code - compiled code // : module - module name to run the code in // // PURPOSE : run a compiled python code in a specific module name // hsBool PythonInterface::RunPYC(PyObject* code, PyObject* module) { PyObject *d, *v; // make sure that we're given a good module... or at least one with an address if ( !module ) { // if no module was given then use just use the main module module = PyImport_AddModule("__main__"); if (module == NULL) return false; } // get the dictionaries for this module d = PyModule_GetDict(module); // run the string v = PyEval_EvalCode((PyCodeObject*)code, d, d); // check for errors and print them if (v == NULL) { // Yikes! errors! PyErr_Print(); return false; } Py_DECREF(v); if (Py_FlushLine()) PyErr_Clear(); return true; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetModuleItem // PARAMETERS : item - what item in the plasma module to get // // PURPOSE : get an item (probably a function) from a specific module // PyObject* PythonInterface::GetModuleItem(char* item, PyObject* module) { if ( module ) { PyObject* d = PyModule_GetDict(module); return PyDict_GetItemString(d, item); } return nil; }