Developer Documentation
PyLogHook.h
1 //MIT License
2 //
3 //Copyright(c) 2017 Matthias M�ller
4 //https://github.com/TinyTinni/PyLogHook
5 //
6 //Permission is hereby granted, free of charge, to any person obtaining a copy
7 //of this software and associated documentation files(the "Software"), to deal
8 //in the Software without restriction, including without limitation the rights
9 //to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10 //copies of the Software, and to permit persons to whom the Software is
11 //furnished to do so, subject to the following conditions :
12 //
13 //The above copyright notice and this permission notice shall be included in all
14 //copies or substantial portions of the Software.
15 //
16 //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19 //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 //SOFTWARE.
23 
24 #pragma once
25 
26 #include <utility>
27 #include <string>
28 
29 #ifdef TYTI_PYLOGHOOK_USE_BOOST
30 #include <boost/python.hpp>
31 #else
32 #include <pybind11/pybind11.h>
33 #endif
34 
35 
36 namespace tyti {
37  namespace pylog {
38  namespace detail {
39 
40 #ifdef TYTI_PYLOGHOOK_USE_BOOST
41  template <typename T>
42  inline boost::python::object LogHookMakeObject(T t)
43  {
44  return boost::python::object(boost::python::make_function(
45  std::forward<T>(t),
46  boost::python::default_call_policies(),
47  boost::mpl::vector<void, const char*>() // signature
48  ));
49  }
50 #else
51  template<typename T>
52  inline pybind11::object LogHookMakeObject(T t)
53  {
54  return pybind11::cpp_function(std::forward<T>(t));
55  }
56 
57 #endif
58  template<typename T>
59  void redirect_syspipe(T t, const char* pipename)
60  {
61  assert(Py_IsInitialized());
62 
63  PyObject* out = PySys_GetObject(pipename);
64 
65  // in case python couldnt create stdout/stderr
66  // this happens in some gui application
67  // just register a new nameless type for this
68 
69  if (out == NULL || out == Py_None)
70  {
71  std::string register_read_write = std::string("import sys\n\
72 sys.") + pipename + std::string(" = type(\"\",(object,),{\"write\":lambda self, txt: None, \"flush\":lambda self: None})()\n");
73 
74  PyRun_SimpleString(register_read_write.c_str());
75  out = PySys_GetObject(pipename);
76  }
77  // overwrite write function
78  PyObject_SetAttrString(out, "write",
79  detail::LogHookMakeObject(std::forward<T>(t)).ptr());
80 
81  }
82  } // namespace detail
83 
99  template<typename T>
100  inline void redirect_stdout(T t)
101  {
102  detail::redirect_syspipe(std::forward<T>(t), "stdout");
103  }
104 
105  template<typename T>
106  inline void redirect_stderr(T t)
107  {
108  detail::redirect_syspipe(std::forward<T>(t), "stderr");
109  }
110  }
111 }
Definition: PyLogHook.h:36