text: // =============================================================================
  // PROJECT CHRONO - http://projectchrono.org
  //
  // Copyright (c) 2014 projectchrono.org
  // All rights reserved.
  //
  // Use of this source code is governed by a BSD-style license that can be found
  // in the LICENSE file at the top level of the distribution and at
  // http://projectchrono.org/license-chrono.txt.
  //
  // =============================================================================
  
  #include "chrono_pyparser/ChSwigutils.h"
  
  #include "chrono_pyparser/ChPython.h"
  #include <Python.h>
  #include <iostream>
  #include <sstream>
  #include <typeinfo>
  
  namespace chrono {
  
  ChPythonEngine::ChPythonEngine() {
      Py_Initialize();
  }
  
  ChPythonEngine::~ChPythonEngine() {
      Py_Finalize();
  }
  
  void ChPythonEngine::Run(const char* program) {
      // Redirect stderr to one std::string buffer.
  
      std::streambuf *msgErrBuffer, *msgErrBufferBackup;
      std::stringstream smessageError;
      msgErrBufferBackup = std::cerr.rdbuf();
      msgErrBuffer = smessageError.rdbuf();
      std::cerr.rdbuf(msgErrBuffer);
  
      if (PyRun_SimpleString(program) != 0) {
          PyErr_Print();
          throw ChException(smessageError.str());
      }
  
      // Set to previous channels!
  
      // std::cout.rdbuf(msgOutBufferBackup);
  
      std::cerr.rdbuf(msgErrBufferBackup);
  }
  
  bool ChPythonEngine::GetFloat(const char* variable, double& return_val) {
      PyObject* module = PyImport_AddModule("__main__");  // borrowed reference
      assert(module);                                     // __main__ should always exist
  
      PyObject* dictionary = PyModule_GetDict(module);  // borrowed reference
      assert(dictionary);                               // __main__ should have a dictionary
  
      PyObject* result = PyDict_GetItemString(dictionary, variable);  // borrowed reference
      if (!result)
          return false;
  
      if (PyFloat_Check(result)) {
          return_val = PyFloat_AS_DOUBLE(result);
          return true;
      }
      if (PyLong_Check(result)) {
          return_val = (double)PyLong_AsLong(result);  // cast py int to c++ double - it's ok anyway
          return true;
      }
  
      return false;
  }
  
  void ChPythonEngine::SetFloat(const char* variable, const double val) {
      std::ostringstream sstream;
      sstream << variable << "=" << val << "\n";
  
      this->Run(sstream.str().c_str());
  }
  
  bool ChPythonEngine::GetInteger(const char* variable, int& return_val) {
      PyObject* module = PyImport_AddModule("__main__");  // borrowed reference
      assert(module);                                     // __main__ should always exist
  
      PyObject* dictionary = PyModule_GetDict(module);  // borrowed reference
      assert(dictionary);                               // __main__ should have a dictionary
  
      PyObject* result = PyDict_GetItemString(dictionary, variable);  // borrowed reference
      if (!result)
          return false;
  
      if (PyLong_Check(result)) {
          return_val = PyLong_AsLong(result);
          return true;
      }
  
      return false;
  }
  
  void ChPythonEngine::SetInteger(const char* variable, const int val) {
      std::ostringstream sstream;
      sstream << variable << "=" << val << "\n";
  
      this->Run(sstream.str().c_str());
  }
  
  bool ChPythonEngine::GetBool(const char* variable, bool& return_val) {
      PyObject* module = PyImport_AddModule("__main__");  // borrowed reference
      assert(module);                                     // __main__ should always exist
  
      PyObject* dictionary = PyModule_GetDict(module);  // borrowed reference
      assert(dictionary);                               // __main__ should have a dictionary
  
      PyObject* result = PyDict_GetItemString(dictionary, variable);  // borrowed reference
      if (!result)
          return false;
  
      if (PyBool_Check(result)) {
          return_val = (PyLong_AsLong(result) == 0) ? false : true;
          return true;
      }
  
      return false;
  }
  
  void ChPythonEngine::SetBool(const char* variable, const bool val) {
      std::ostringstream sstream;
      sstream << variable << "=" << val << "\n";
  
      this->Run(sstream.str().c_str());
  }
  
  bool ChPythonEngine::GetString(const char* variable, std::string& return_val) {
      PyObject* module = PyImport_AddModule("__main__");  // borrowed reference
      assert(module);                                     // __main__ should always exist
  
      PyObject* dictionary = PyModule_GetDict(module);  // borrowed reference
      assert(dictionary);                               // __main__ should have a dictionary
  
      PyObject* result = PyDict_GetItemString(dictionary, variable);  // borrowed reference
      if (!result)
          return false;
  
      if (PyBytes_Check(result)) {
          char* ret_string = PyBytes_AsString(result);
          return_val = ret_string;
          return true;
      }
      if (PyUnicode_Check(result)) {
          PyObject* mascii = PyUnicode_AsASCIIString(result);
  
          char* ret_string = PyBytes_AsString(mascii);
          return_val = ret_string;
  
          Py_DECREF(mascii);
          return true;
      }
  
      return false;
  }
  
  void ChPythonEngine::SetString(const char* variable, std::string& val) {
      std::ostringstream sstream;
      sstream << variable << "='" << val << "'\n";
  
      this->Run(sstream.str().c_str());
  }
  
  /*
  typedef struct {
    PyObject ob_base;
    void *ptr;
    void *ty;
    int own;
    PyObject *next;
  
  } SwigPyObject;
  */
  
  void ChPythonEngine::ImportSolidWorksSystem(const char* solidworks_py_file, ChSystemNSC& msystem) {
      std::ostringstream sstream;
  
      // sstream << "from " << std::string(solidworks_py_file) << " import exported_items\n";
  
      sstream << "import builtins  \n";
      sstream << "import imp  \n";
      sstream << "import os  \n";
      sstream << "mdirname, mmodulename= os.path.split('" << std::string(solidworks_py_file) << "')  \n";
      sstream << "builtins.exported_system_relpath = mdirname + '/'  \n";
      sstream << "fp, pathname, description = imp.find_module(mmodulename,[builtins.exported_system_relpath])  \n";
      sstream << "try:  \n";
      sstream << "    imported_mod = imp.load_module('imported_mod', fp, pathname, description)  \n";
      sstream << "finally:  \n";
      sstream << "    if fp:  \n";
      sstream << "        fp.close()  \n";
      sstream << "exported_items = imported_mod.exported_items  \n";
  
      this->Run(sstream.str().c_str());
  
      PyObject* module = PyImport_AddModule("__main__");  // borrowed reference
      if (!module)
          throw ChException("ERROR. No Python __main__ module?");
  
      PyObject* dictionary = PyModule_GetDict(module);  // borrowed reference
      if (!dictionary)
          throw ChException("ERROR. No Python dictionary?");
  
      PyObject* result = PyDict_GetItemString(dictionary, "exported_items");  // borrowed reference
      if (!result)
          throw ChException("ERROR. Missing Python object 'exported_items' in SolidWorks file");
  
      if (PyList_Check(result)) {
          int nitems = (int)PyList_Size(result);
          // GetLog() << "N.of list items: " << nitems << "\n";
          for (int i = 0; i < nitems; i++) {
              PyObject* mobj = PyList_GetItem(result, i);
              if (mobj) {
                  // GetLog() << "   Python type: " << mobj->ob_type->tp_name << "\n";
  
                  SwigPyObject* mswigobj = SWIG_Python_GetSwigThis(mobj);
                  if (mswigobj) {
                      void* objptr = mswigobj->ptr;
                      std::shared_ptr<ChPhysicsItem>* pt_to_shp = (std::shared_ptr<ChPhysicsItem>*)objptr;
  
                      /// Add the ChPhysicsItem to the ChSystem
                      msystem.Add((*pt_to_shp));
                  } else {
                      throw ChException(
                          "ERROR. Only shared pointers to ChPhysicsItem subclasses can be inside exported_items.");
                  }
              }
          }
  
          msystem.Setup();
          msystem.Update();
  
      } else {
          throw ChException("ERROR. exported_items python object is not a list.");
      }
  }
  
  }  // namespace chrono
  
  