#include "StdAfx.h" #include ".\PythonDLL.h" #include "ValuesModule.h" CPythonDLL::CPythonDLL(void) { } CPythonDLL::~CPythonDLL(void) { int nIsInit = Py_IsInitialized(); if (nIsInit) Py_Finalize(); } void CPythonDLL::init(std::string& scriptName) { // Register the extension module if ( PyImport_AppendInittab("Values", initValues) == -1 ) { throw python_exception( "Failed to add Values to the interpreter's builtin modules" ); } // Initialize the Python interpreter Py_Initialize(); // Set up so sys.path contain our script path std::string pyinitstr( "import sys\n" "sys.path.append(\"##SCRIPTPATH##\")\n" "\n" ); // Build full path to scripts // For now, we hardcode the path where the scripts are located // Typically this would be read from a configuration file std::string scr_path = "c:/scripts"; // Insert path into init string std::string placeHolder("##SCRIPTPATH##"); unsigned int pos = pyinitstr.find(placeHolder); if( pos != std::string::npos ) { pyinitstr.erase(pos, placeHolder.length()); pyinitstr.insert(pos, scr_path); } // Run the init script to set up sys.path if( PyRun_SimpleString(const_cast(pyinitstr.c_str())) != NULL ) throw python_exception("C++ : Warning: Could not set up sys.path"); // Import the module, storing the pointer in a handle<> try { module = importModule(scriptName); } catch (...) { python_exception exc = getExceptionDetail(); throw(exc); } } void CPythonDLL::finalize() { Py_Finalize(); } const char* CPythonDLL::getVersion(void) { return Py_GetVersion(); } const char* CPythonDLL::getCopyright(void) { return Py_GetCopyright(); } void CPythonDLL::eval(const char* code) { try { object main_module (( handle<>( borrowed( PyImport_AddModule("__main__") ) ) )); object main_namespace = main_module.attr("__dict__"); // Insert the app's global value_obj into the python dictionary /*if ( PyDict_SetItem( main_namespace.ptr() , PyString_FromString("valueobj") , value_obj.ptr() ) == -1 ) { throw python_exception( "Could not add value_obj to the dictionary!" ); }*/ handle<> ignored(( PyRun_String( code , Py_file_input , main_namespace.ptr() , main_namespace.ptr() ) )); } catch (...) { python_exception exc = getExceptionDetail(); throw(exc); } } void CPythonDLL::eval(std::string& code) { this->eval( const_cast(code.c_str()) ); } void CPythonDLL::callfunc(const std::string fname, object& obj) { try { object func = getFunction(const_cast(fname.c_str())); func(obj); } catch(...) { python_exception exc = getExceptionDetail(); throw(exc); } } handle<> CPythonDLL::importModule(std::string module_name) { PyObject *module_ptr = PyImport_ImportModule(const_cast(module_name.c_str())); if( module_ptr == NULL) { python_exception exc = getExceptionDetail(); throw(exc); } return handle<>(module_ptr); } python_exception CPythonDLL::getExceptionDetail() { std::string errmsg(""); int nIsInit = Py_IsInitialized(); if (!nIsInit) { errmsg = "Python not initialized!"; return python_exception( errmsg ); } // Extra paranoia... if (!PyErr_Occurred()) { errmsg = "Not a python error!"; return python_exception( errmsg ); } PyObject* exc_type; PyObject* exc_value; PyObject* exc_traceback; PyObject* pystring; PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); if( exc_type == NULL && exc_value == NULL && exc_traceback== NULL) { errmsg = "Strange: Nothing to report"; } else { pystring = NULL; if ( exc_type != NULL && (pystring = PyObject_Str(exc_type)) != NULL && (PyString_Check(pystring)) ) { errmsg += PyString_AsString(pystring); } else { errmsg += ""; } Py_XDECREF(pystring); pystring = NULL; if ( exc_value != NULL && (pystring = PyObject_Str(exc_value)) != NULL && (PyString_Check(pystring)) ) { errmsg += PyString_AsString(pystring); } else { errmsg += ""; } Py_XDECREF(pystring); Py_XDECREF(exc_type); Py_XDECREF(exc_value); /* caller owns all 3 */ Py_XDECREF(exc_traceback); /* already NULL'd out */ } return python_exception( errmsg ); } object CPythonDLL::getFunction(const char* fname) { PyObject* dict = PyModule_GetDict(module.get()); boost::python::str funcName(fname); return object( handle<>(PyDict_GetItem(dict, funcName.ptr())) ); }