OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PythonEval.h
Go to the documentation of this file.
1 /*
2  * @file opencog/cython/PythonEval.h
3  *
4  * Simple python expression evaluator.
5  *
6  * @author Zhenhua Cai <czhedu@gmail.com>
7  * Ramin Barati <rekino@gmail.com>
8  * Keyvan Mir Mohammad Sadeghi <keyvan@opencog.org>
9  * Curtis Faith <curtis.m.faith@gmail.com>
10  * @date 2011-09-20
11  *
12  * @Note
13  * Zhenhua: Many code are copied directly from original /opencog/cython/PythonModule.h|cc
14  * by Joel. I also borrowed some ideas from SchemeEval.h|cc
15  *
16  * Ramin: This class is completely revised by me and Keyvan. The new code is inspired
17  * by Linas' SchemeEval and borrowed some ideas from Joel's PythonModule.
18  *
19  * @todo
20  *
21  * This program is free software; you can redistribute it and/or modify
22  * it under the terms of the GNU Affero General Public License v3 as
23  * published by the Free Software Foundation and including the exceptions
24  * at http://opencog.org/wiki/Licenses
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU Affero General Public License
32  * along with this program; if not, write to:
33  * Free Software Foundation, Inc.,
34  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35  */
36 
37 #ifndef OPENCOG_PYTHON_EVAL_H
38 #define OPENCOG_PYTHON_EVAL_H
39 #ifdef HAVE_CYTHON
40 
41 #include "PyIncludeWrapper.h"
42 
43 #include <map>
44 #include <mutex>
45 #include <string>
46 #include <vector>
47 
48 #include <boost/filesystem/operations.hpp>
49 
53 
54 
55 namespace opencog {
56 
57 class AtomSpace;
58 class CogServer;
59 
64 {
65  private:
66  PyGILState_STATE state;
67 
68  public:
69  PythonThreadLocker() : state(PyGILState_Ensure())
70  {}
71 
73  PyGILState_Release(state);
74  }
75 };
76 
82 class PythonEval : public GenericEval
83 {
84  private:
86 
87  // Module utility functions
88  void import_module( const boost::filesystem::path &file,
89  PyObject* pyFromList);
90  void add_module_directory(const boost::filesystem::path &directory);
91  void add_module_file(const boost::filesystem::path &file);
92  void add_modules_from_path(std::string path);
93  void add_modules_from_abspath(std::string path);
94 
95  // Python utility functions
96  PyObject* call_user_function(const std::string& func,
97  Handle varargs);
98  void build_python_error_message(const char* function_name,
99  std::string& errorMessage);
100  void add_to_sys_path(std::string path);
101  PyObject * atomspace_py_object(AtomSpace *);
102  void print_dictionary(PyObject*);
103  void execute_string(const char* command);
104  int argument_count(PyObject* pyFunction);
105  PyObject* module_for_function(const std::string& moduleFunction,
106  std::string& functionName);
107 
109 
111  // Resource Acquisition is Allocation, for the current AtomSpace.
112  // If anything throws an exception, then dtor runs and restores
113  // the old atomspace.
114  struct RAII {
115  RAII(PythonEval* pev, AtomSpace* as) : _pev(pev)
116  { _save_as = pev->_atomspace; pev->_atomspace = as; }
120  };
121 
122  // Single, global mutex for serializing access to the atomspace.
123  // The singleton-instance design of this class forces us to
124  // serialize access (the GIL is not enough), because there is
125  // no way to guarantee that python won't accidentally be called
126  // from multiple threads. That's because the EvaluationLink
127  // is called from scheme and from the pattern matcher, and its
128  // unknown how many threads those things might be running in.
129  // The lock is recursive, because we may need to use multiple
130  // different atomspaces with the evaluator, in some nested
131  // fashion. So this lock prevents other threads from using the
132  // wrong atomspace in some other thread. Unfort
133  static std::recursive_mutex _mtx;
134 
135  PyObject* _pyGlobal;
136  PyObject* _pyLocal;
137  PyObject* _pyRootModule;
138 
139  PyObject* _pySysPath;
140 
141  std::map <std::string, PyObject*> _modules;
142 
143  std::string _result;
145 
146  public:
148  ~PythonEval();
149 
153  static void create_singleton_instance(AtomSpace*);
154 
158  static void delete_singleton_instance();
159 
163  static PythonEval & instance(AtomSpace* atomspace = NULL);
164 
165  // The async-output interface.
166  virtual void begin_eval() {}
167  virtual void eval_expr(const std::string&);
168  virtual std::string poll_result();
169 
170  // The synchronous-output interface.
171  std::string eval(const std::string& expr)
172  { begin_eval(); eval_expr(expr); return poll_result(); }
173 
177  std::string apply_script(const std::string& script);
178 
182  Handle apply(AtomSpace*, const std::string& func, Handle varargs);
183 
187  TruthValuePtr apply_tv(AtomSpace*, const std::string& func, Handle varargs);
188 
193  { this->print_dictionary(PyModule_GetDict(_pyRootModule)); }
194 
195 };
196 
202 
207 
208 } /* namespace opencog */
209 
210 #endif /* HAVE_CYTHON */
211 #endif /* OPENCOG_PYTHON_EVAL_H */
PyObject * _pySysPath
Definition: PythonEval.h:139
int argument_count(PyObject *pyFunction)
Definition: PythonEval.cc:609
virtual std::string poll_result()
Definition: PythonEval.cc:1264
void add_modules_from_abspath(std::string path)
Definition: PythonEval.cc:1161
std::shared_ptr< TruthValue > TruthValuePtr
Definition: TruthValue.h:85
PythonEval(AtomSpace *)
Definition: PythonEval.cc:343
std::string apply_script(const std::string &script)
Definition: PythonEval.cc:902
void build_python_error_message(const char *function_name, std::string &errorMessage)
Definition: PythonEval.cc:554
PyObject * module_for_function(const std::string &moduleFunction, std::string &functionName)
Definition: PythonEval.cc:641
AtomSpace * _atomspace
Definition: PythonEval.h:110
void add_modules_from_path(std::string path)
Definition: PythonEval.cc:1125
void print_root_dictionary()
Definition: PythonEval.h:192
PyObject * _pyRootModule
Definition: PythonEval.h:137
void print_dictionary(PyObject *)
Definition: PythonEval.cc:525
void global_python_finalize()
Definition: PythonEval.cc:329
void add_module_file(const boost::filesystem::path &file)
Definition: PythonEval.cc:1098
static PythonEval & instance(AtomSpace *atomspace=NULL)
Definition: PythonEval.cc:416
static void delete_singleton_instance()
Definition: PythonEval.cc:407
void initialize_python_objects_and_imports(void)
Definition: PythonEval.cc:451
void add_to_sys_path(std::string path)
Definition: PythonEval.cc:973
std::string eval(const std::string &expr)
Definition: PythonEval.h:171
void import_module(const boost::filesystem::path &file, PyObject *pyFromList)
Definition: PythonEval.cc:992
PyObject * _pyLocal
Definition: PythonEval.h:136
Handle apply(AtomSpace *, const std::string &func, Handle varargs)
Definition: PythonEval.cc:799
virtual void begin_eval()
Definition: PythonEval.h:166
std::map< std::string, PyObject * > _modules
Definition: PythonEval.h:141
static void create_singleton_instance(AtomSpace *)
Definition: PythonEval.cc:399
PyObject * atomspace_py_object(AtomSpace *)
Definition: PythonEval.cc:491
void add_module_directory(const boost::filesystem::path &directory)
Definition: PythonEval.cc:1056
PyGILState_STATE state
Definition: PythonEval.h:66
virtual void eval_expr(const std::string &)
Definition: PythonEval.cc:1192
PyObject * _pyGlobal
Definition: PythonEval.h:135
RAII(PythonEval *pev, AtomSpace *as)
Definition: PythonEval.h:115
void global_python_initialize()
Definition: PythonEval.cc:263
TruthValuePtr apply_tv(AtomSpace *, const std::string &func, Handle varargs)
Definition: PythonEval.cc:851
static PythonEval * singletonInstance
Definition: PythonEval.h:108
static std::recursive_mutex _mtx
Definition: PythonEval.h:133
std::string _result
Definition: PythonEval.h:143
PyObject * call_user_function(const std::string &func, Handle varargs)
Definition: PythonEval.cc:668
void execute_string(const char *command)
Definition: PythonEval.cc:598