i6engine  1.0
PythonScriptingManager.h
Go to the documentation of this file.
1 /*
2  * i6engine
3  * Copyright (2016) Daniel Bonrath, Michael Baer, All rights reserved.
4  *
5  * This file is part of i6engine; i6engine is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
25 #ifndef __I6ENGINE_MODULES_PYTHONSCRIPTINGMANAGER_H__
26 #define __I6ENGINE_MODULES_PYTHONSCRIPTINGMANAGER_H__
27 
28 #include <set>
29 
31 #include "i6engine/utils/Future.h"
33 
35 
36 #include "boost/python.hpp"
37 
38 namespace i6e {
39 namespace api {
40  class ScriptingFacade;
41 } /* namespace api */
42 namespace modules {
43 
44  class PythonScriptingMailbox;
45 
47  friend class PythonScriptingMailbox;
48  friend class api::ScriptingFacade;
49 
50  public:
55 
60 
61  void Tick();
62 
66  template<typename Ret, typename... args>
67  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callScript(const std::string & file, const std::string & func, args... B) {
68  _callScripts.push(std::bind([this, file, func](args... A) {
69  ASSERT_THREAD_SAFETY_FUNCTION
70  parseScript(file, false);
71 
72  try {
73  boost::python::object module = boost::python::import("__main__");
74  boost::python::object global = module.attr("__dict__");
75  boost::python::object f = global[func];
76  boost::python::call<Ret>(f.ptr(), A...);
77  } catch (const boost::python::error_already_set &) {
78  logStacktrace();
79  }
80  }, B...));
81  }
82 
86  template<typename Ret, typename... args>
87  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callScript(const std::string & file, const std::string & func, args... B) {
88  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
89  _callScripts.push(std::bind([this, file, func, ret](args... A) {
90  ASSERT_THREAD_SAFETY_FUNCTION
91  parseScript(file, false);
92 
93  try {
94  boost::python::object module = boost::python::import("__main__");
95  boost::python::object global = module.attr("__dict__");
96  boost::python::object f = global[func];
97  ret->push(boost::python::call<Ret>(f.ptr(), A...));
98  } catch (const boost::python::error_already_set &) {
99  logStacktrace();
100  }
101  }, B...));
102  return ret;
103  }
104 
108  template<typename Ret, typename... args>
109  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callFunction(const std::string & func, args... B) {
110  _callScripts.push(std::bind([this, func](args... A) {
111  ASSERT_THREAD_SAFETY_FUNCTION
112  try {
113  boost::python::object module = boost::python::import("__main__");
114  boost::python::object global = module.attr("__dict__");
115  boost::python::object f = global[func];
116  boost::python::call<Ret>(f.ptr(), A...);
117  } catch (const boost::python::error_already_set &) {
118  logStacktrace();
119  }
120  }, B...));
121  }
122 
126  template<typename Ret, typename... args>
127  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callFunction(const std::string & func, args... B) {
128  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
129  _callScripts.push(std::bind([this, func, ret](args... A) {
130  ASSERT_THREAD_SAFETY_FUNCTION
131  try {
132  boost::python::object module = boost::python::import("__main__");
133  boost::python::object global = module.attr("__dict__");
134  boost::python::object f = global[func];
135  ret->push(boost::python::call<Ret>(f.ptr(), A...));
136  } catch (const boost::python::error_already_set &) {
137  logStacktrace();
138  }
139  }, B...));
140  return ret;
141  }
142 
146  template<typename Ret, typename... args>
147  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callScriptWithCallback(const std::string & file, const std::string & func, const std::function<void(void)> & callback, args... B) {
148  _callScripts.push(std::bind([this, file, func, callback](args... A) {
149  ASSERT_THREAD_SAFETY_FUNCTION
150  parseScript(file, false);
151  try {
152  boost::python::object module = boost::python::import("__main__");
153  boost::python::object global = module.attr("__dict__");
154  boost::python::object f = global[func];
155  boost::python::call<Ret>(f.ptr(), A...);
156  } catch (const boost::python::error_already_set &) {
157  logStacktrace();
158  }
159  callback();
160  }, B...));
161  }
162 
166  template<typename Ret, typename... args>
167  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callScriptWithCallback(const std::string & file, const std::string & func, const std::function<void(void)> & callback, args... B) {
168  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
169  _callScripts.push(std::bind([this, file, func, callback, ret](args... A) {
170  ASSERT_THREAD_SAFETY_FUNCTION
171  parseScript(file, false);
172  try {
173  boost::python::object module = boost::python::import("__main__");
174  boost::python::object global = module.attr("__dict__");
175  boost::python::object f = global[func];
176  ret->push(boost::python::call<Ret>(f.ptr(), A...));
177  } catch (const boost::python::error_already_set &) {
178  logStacktrace();
179  }
180  callback();
181  }, B...));
182  return ret;
183  }
184 
188  template<typename Ret, typename... args>
189  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callFunctionWithCallback(const std::string & func, const std::function<void(void)> & callback, args... B) {
190  _callScripts.push(std::bind([this, func, callback](args... A) {
191  ASSERT_THREAD_SAFETY_FUNCTION
192  try {
193  boost::python::object module = boost::python::import("__main__");
194  boost::python::object global = module.attr("__dict__");
195  boost::python::object f = global[func];
196  boost::python::call<Ret>(f.ptr(), A...);
197  } catch (const boost::python::error_already_set &) {
198  logStacktrace();
199  }
200  callback();
201  }, B...));
202  }
203 
207  template<typename Ret, typename... args>
208  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callFunctionWithCallback(const std::string & func, const std::function<void(void)> & callback, args... B) {
209  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
210  _callScripts.push(std::bind([this, func, callback, ret](args... A) {
211  ASSERT_THREAD_SAFETY_FUNCTION
212  try {
213  boost::python::object module = boost::python::import("__main__");
214  boost::python::object global = module.attr("__dict__");
215  boost::python::object f = global[func];
216  ret->push(boost::python::call<Ret>(f.ptr(), A...));
217  } catch (const boost::python::error_already_set &) {
218  logStacktrace();
219  }
220  callback();
221  }, B...));
222  return ret;
223  }
224 
228  template<typename T>
229  typename std::enable_if<std::is_pointer<T>::value>::type setGlobalVariable(const std::string & name, T value) {
230  _callScripts.push(std::bind([this, name, value]() {
232  boost::python::scope().attr(name.c_str()) = value;
233  }));
234  }
235 
239  void loadAllScripts();
240 
241  private:
242  std::set<std::string> _scripts;
243  std::string _scriptsPath;
244  utils::DoubleBufferQueue<std::function<void(void)>, true, false> _callScripts;
245 
249  void News(const api::GameMessage::Ptr & msg);
250 
254  void parseScript(const std::string & file, bool completePath);
255 
259  void logStacktrace();
260 
265 
269  PythonScriptingManager & operator=(const PythonScriptingManager &) = delete;
270 
272  };
273 
274 } /* namespace modules */
275 } /* namespace i6e */
276 
277 #endif /* __I6ENGINE_MODULES_PYTHONSCRIPTINGMANAGER_H__ */
278 
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callScriptWithCallback(const std::string &file, const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method in the given script with return type non-void and calls callback after exec...
std::enable_if< std::is_void< Ret >::value, Ret >::type callScriptWithCallback(const std::string &file, const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method in the given script with return type void and calls callback after executio...
#define ASSERT_THREAD_SAFETY_FUNCTION
#define ISIXE_MODULES_API
std::enable_if< std::is_void< Ret >::value, Ret >::type callFunctionWithCallback(const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method with return type void and calls callback after execution of the script ...
boost::shared_ptr< Message > Ptr
Definition: Message.h:66
std::enable_if< std::is_pointer< T >::value >::type setGlobalVariable(const std::string &name, T value)
sets a global variable
std::enable_if< std::is_void< Ret >::value, Ret >::type callScript(const std::string &file, const std::string &func, args...B)
executes the given method in the given script with return type void
#define ASSERT_THREAD_SAFETY_HEADER
std::enable_if< std::is_void< Ret >::value, Ret >::type callFunction(const std::string &func, args...B)
executes the given method with return type void
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callFunctionWithCallback(const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method with return type non-void and calls callback after execution of the script ...
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callFunction(const std::string &func, args...B)
executes the given method with return type non-void
Handles the incoming messages on the scripting channel and calls the corresponding methods...
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callScript(const std::string &file, const std::string &func, args...B)
executes the given method in the given script with return type non-void