interpreter.cc 6.69 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// -*- mode: c++ -*-
// Copyright 2011, Florent Lamiraux, CNRS.
//
// This file is part of dynamic-graph-python.
// dynamic-graph is free software: you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// dynamic-graph 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 Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// dynamic-graph. If not, see <http://www.gnu.org/licenses/>.

#include <iostream>
#include "dynamic-graph/python/interpreter.hh"
19
#include "link-to-python.hh"
20
21
22
23

// Python initialization commands
namespace dynamicgraph {
  namespace python {
Florent Lamiraux's avatar
Florent Lamiraux committed
24
    static const std::string pythonPrefix[5] = {
25
      "import traceback\n",
26
27
28
29
30
31
32
33
34
35
36
37
38
      "def display(s): return str(s) if not s is None else None",
      "class StdoutCatcher:\n"
      "    def __init__(self):\n"
      "        self.data = ''\n"
      "    def write(self, stuff):\n"
      "        self.data = self.data + stuff\n"
      "    def fetch(self):\n"
      "        s = self.data[:]\n"
      "        self.data = ''\n"
      "        return s\n"
      "stdout_catcher = StdoutCatcher()\n"
      "import sys\n"
      "sys.stdout = stdout_catcher"
39
40
41
42
43
    };
  }
}

using dynamicgraph::python::Interpreter;
44
using dynamicgraph::python::libpython;
45
46
47

Interpreter::Interpreter()
{
48
49
  // load python dynamic library
  // this is silly, but required to be able to import dl module.
50
#ifndef WIN32
51
  dlopen(libpython.c_str(), RTLD_LAZY | RTLD_GLOBAL);
52
#endif
53
54
55
56
57
58
59
60
61
  Py_Initialize();
  mainmod_ = PyImport_AddModule("__main__");
  Py_INCREF(mainmod_);
  globals_ = PyModule_GetDict(mainmod_);
  assert(globals_);
  Py_INCREF(globals_);
  PyRun_SimpleString(pythonPrefix[0].c_str());
  PyRun_SimpleString(pythonPrefix[1].c_str());
  PyRun_SimpleString(pythonPrefix[2].c_str());
62
  PyRun_SimpleString(pythonPrefix[3].c_str());
Florent Lamiraux's avatar
Florent Lamiraux committed
63
  PyRun_SimpleString(pythonPrefix[4].c_str());
64
65
66
67
68
69
70
71
  traceback_format_exception_ = PyDict_GetItemString
    (PyModule_GetDict(PyImport_AddModule("traceback")), "format_exception");
  assert(PyCallable_Check(traceback_format_exception_));
  Py_INCREF(traceback_format_exception_);
}

Interpreter::~Interpreter()
{
Florent Lamiraux's avatar
Florent Lamiraux committed
72
73
74
  //Py_DECREF(mainmod_);
  //Py_DECREF(globals_);
  //Py_DECREF(traceback_format_exception_);
75
76
77
78
79
80
  Py_Finalize();
}

std::string Interpreter::python( const std::string& command )
{
  PyObject* result = PyRun_String(command.c_str(), Py_eval_input, globals_,
81
                                  globals_);
82
83
84
  if (!result) {
    PyErr_Clear();
    result = PyRun_String(command.c_str(), Py_single_input, globals_,
85
                          globals_);
86
87
88
89
90
91
  }
  if (result == NULL) {
    if (PyErr_Occurred()) {
      PyObject *ptype, *pvalue, *ptraceback;
      PyErr_Fetch(&ptype, &pvalue, &ptraceback);
      if (ptraceback == NULL) {
92
        ptraceback = Py_None;
93
94
95
96
97
98
99
100
101
102
      }
      PyObject* args = PyTuple_New(3);
      PyTuple_SET_ITEM(args, 0, ptype);
      PyTuple_SET_ITEM(args, 1, pvalue);
      PyTuple_SET_ITEM(args, 2, ptraceback);
      result = PyObject_CallObject(traceback_format_exception_, args);
      assert(PyList_Check(result));
      unsigned int size = PyList_GET_SIZE(result);
      std::string stringRes;
      for (unsigned int i=0; i<size; i++) {
103
        stringRes += std::string(PyString_AsString(PyList_GET_ITEM(result, i)));
104
105
106
107
108
109
110
      }
      result  = PyString_FromString(stringRes.c_str());
      PyErr_Clear();
    } else {
      std::cout << "Result is NULL but no error occurred." << std::endl;
    }
  } else {
111
    result = PyObject_Repr(result);
112
  }
113
114
115
116
117
  std::string value = "";
  // PyString_AsString will generate a segv if result is NULL.
  // This might be the case if PyObject_Repr fails.
  if (result!=NULL)
    value = PyString_AsString(result);
118
119
120
  return value;
}

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
void Interpreter::python( const std::string& command, std::string& res,
                          std::string& out, std::string& err)
{
  res = "";
  out = "";
  err = "";
  PyObject* result = PyRun_String(command.c_str(), Py_eval_input, globals_,
				  globals_);
  if (!result) {
    PyErr_Clear();
    result = PyRun_String(command.c_str(), Py_single_input, globals_,
				  globals_);
  }

  if (result == NULL) {
    if (PyErr_Occurred()) {
      PyObject *ptype, *pvalue, *ptraceback, *pyerr;
      PyErr_Fetch(&ptype, &pvalue, &ptraceback);
      if (ptraceback == NULL) {
        ptraceback = Py_None;
      }
      PyObject* args = PyTuple_New(3);
      PyTuple_SET_ITEM(args, 0, ptype);
      PyTuple_SET_ITEM(args, 1, pvalue);
      PyTuple_SET_ITEM(args, 2, ptraceback);
      pyerr = PyObject_CallObject(traceback_format_exception_, args);
      assert(PyList_Check(pyerr));
      unsigned int size = PyList_GET_SIZE(pyerr);
      std::string stringRes;
      for (unsigned int i=0; i<size; i++) {
        stringRes += std::string(PyString_AsString(PyList_GET_ITEM(pyerr, i)));
      }
      pyerr  = PyString_FromString(stringRes.c_str());
      err = PyString_AsString(pyerr);
      PyErr_Clear();
    } else {
      std::cout << "Result is NULL but no error occurred." << std::endl;
    }
  }
  PyObject* stdout_obj = PyRun_String("stdout_catcher.fetch()",
                                      Py_eval_input, globals_,
                                      globals_);
  out = PyString_AsString(stdout_obj);
164
  // Local display for the robot (in debug mode or for the logs)
165
166
  std::cout << out;
  result = PyObject_Repr(result);
167
168
169
170
  // If python cannot build a string representation of result
  // then results is equal to NULL. This will trigger a SEGV
  if (result!=NULL)
    res = PyString_AsString(result);
171
172
173
  return;
}

174
175
176
177
178
PyObject* Interpreter::globals()
{
  return globals_;
}

179
180
void Interpreter::runPythonFile( std::string filename )
{
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  PyObject* pymainContext = globals_;
  PyRun_File(fopen( filename.c_str(),"r" ), filename.c_str(),
	     Py_file_input, pymainContext,pymainContext);
  if (PyErr_Occurred())
    {
      std::cout << "Error occures..." << std::endl;
      PyErr_Print();
    }
}

void Interpreter::runMain( void )
{
  const char * argv [] = { "dg-embedded-pysh" };
  Py_Main(1,const_cast<char**>(argv));
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
}

std::string Interpreter::processStream(std::istream& stream, std::ostream& os)
{
  char line[10000]; sprintf(line, "%s", "\n");
  std::string command;
  std::streamsize maxSize = 10000;
#if 0
  while (line != std::string("")) {
    stream.getline(line, maxSize, '\n');
    command += std::string(line) + std::string("\n");
  };
#else
  os << "dg> ";
  stream.getline(line, maxSize, ';');
  command += std::string(line);
#endif
  return command;
}