DynExp
Highly flexible laboratory automation for dynamically changing experiments.
PyUtil.h
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
8 #pragma once
9 
10 #include "stdafx.h"
11 
12 namespace py = pybind11;
13 
14 namespace Util
15 {
19  static constexpr auto PyTab = " ";
20 
25  {
26  public:
31  void write(std::string Str);
32 
36  void flush() {}
37  };
38 
43  {
44  public:
46 
47  void PrintDebugInfo();
48 
49  private:
50  // Do not change order. GILRelease needs to be destroyed first upon destruction.
52  py::scoped_interpreter Interpreter;
53  py::module_ Module_sys;
54  py::gil_scoped_release GILRelease;
55  };
56 
63  template <typename T, std::enable_if_t<
64  std::is_base_of_v<py::object, T>, int> = 0
65  >
66  class PyObject
67  {
68  public:
69  using ObjectType = T;
70 
74  PyObject() { Reset(); }
75 
80  PyObject(const T& Object) : Object(std::make_unique<T>(Object)) {}
81 
85  ~PyObject() { Remove(); }
86 
93  {
94  this->Object = std::make_unique<T>(Object);
95  return *this;
96  }
97 
102  auto& Get() const noexcept { return *Object; }
103 
107  auto& Get() noexcept { return *Object; }
108 
113  void Reset()
114  {
115  py::gil_scoped_acquire acquire;
116  Object = std::make_unique<T>();
117  }
118 
127  template <typename... ArgTs>
128  py::object operator()(ArgTs&& ...Args) const
129  {
130  if (Object && !Object->is_none())
131  return (*Object)(std::forward<ArgTs>(Args)...);
132  else
133  return py::none();
134  }
135 
136  private:
140  void Remove()
141  {
142  py::gil_scoped_acquire acquire;
143  Object.reset();
144  }
145 
149  std::unique_ptr<T> Object;
150  };
151 }
Initialize Python interpreter and directly release the GIL after construction.
Definition: PyUtil.h:43
py::module_ Module_sys
Handle to the Python sys module.
Definition: PyUtil.h:53
py::gil_scoped_release GILRelease
Release which releases the GIL at construction.
Definition: PyUtil.h:54
void PrintDebugInfo()
Writes information on the Python interpreter configuration to DynExp's log.
Definition: PyUtil.cpp:51
PyStdoutLoggerWrapper Logger
Wrapper to forward DynExp's event log to Python.
Definition: PyUtil.h:51
py::scoped_interpreter Interpreter
Python interpreter.
Definition: PyUtil.h:52
Wraps a class derived from pybind11::object and ensures that the GIL is acquired when the PyObject is...
Definition: PyUtil.h:67
PyObject(const T &Object)
Copy-constructs a PyObject from Object.
Definition: PyUtil.h:80
auto & Get() const noexcept
Returns the wrapped pybind11::object.
Definition: PyUtil.h:102
std::unique_ptr< T > Object
Object derived from pybind11::object owned by this PyObject instance.
Definition: PyUtil.h:149
PyObject & operator=(const T &Object)
Locks the GIL, removes the owned object and copy-assigns from Object.
Definition: PyUtil.h:92
~PyObject()
Removes the owned pybind11::object after locking the GIL.
Definition: PyUtil.h:85
PyObject()
Constructs an empty PyObject.
Definition: PyUtil.h:74
void Reset()
Removes the owned pybind11::object after locking the GIL.
Definition: PyUtil.h:113
void Remove()
Removes the owned pybind11::object after locking the GIL.
Definition: PyUtil.h:140
py::object operator()(ArgTs &&...Args) const
Calls the wrapped object if it is not nullptr and if the wrapped object is not pybind11::none.
Definition: PyUtil.h:128
auto & Get() noexcept
Returns the wrapped pybind11::object. noexcept
Definition: PyUtil.h:107
Forwards Python's stdout to Util::EventLogger instance defined in Util::EventLog().
Definition: PyUtil.h:25
void write(std::string Str)
Formats the string passed to the function and writes it to the event log.
Definition: PyUtil.cpp:18
void flush()
Required, but does nothing.
Definition: PyUtil.h:36
DynExp's Util namespace contains commonly used functions and templates as well as extensions to Qt an...
Definition: circularbuf.cpp:7
static constexpr auto PyTab
Character sequence to indent a Python instruction by one level.
Definition: PyUtil.h:19
Accumulates include statements to provide a precompiled header.