Scarab  v2.9.0
Project 8 C++ Utility Library
embed.h
Go to the documentation of this file.
1 /*
2  pybind11/embed.h: Support for embedding the interpreter
3 
4  Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>
5 
6  All rights reserved. Use of this source code is governed by a
7  BSD-style license that can be found in the LICENSE file.
8 */
9 
10 #pragma once
11 
12 #include "pybind11.h"
13 #include "eval.h"
14 
15 #if defined(PYPY_VERSION)
16 # error Embedding the interpreter is not supported with PyPy
17 #endif
18 
19 #if PY_MAJOR_VERSION >= 3
20 # define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
21  extern "C" PyObject *pybind11_init_impl_##name() { \
22  return pybind11_init_wrapper_##name(); \
23  }
24 #else
25 # define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
26  extern "C" void pybind11_init_impl_##name() { \
27  pybind11_init_wrapper_##name(); \
28  }
29 #endif
30 
46 #define PYBIND11_EMBEDDED_MODULE(name, variable) \
47  static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \
48  static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \
49  auto m = pybind11::module(PYBIND11_TOSTRING(name)); \
50  try { \
51  PYBIND11_CONCAT(pybind11_init_, name)(m); \
52  return m.ptr(); \
53  } catch (pybind11::error_already_set &e) { \
54  PyErr_SetString(PyExc_ImportError, e.what()); \
55  return nullptr; \
56  } catch (const std::exception &e) { \
57  PyErr_SetString(PyExc_ImportError, e.what()); \
58  return nullptr; \
59  } \
60  } \
61  PYBIND11_EMBEDDED_MODULE_IMPL(name) \
62  pybind11::detail::embedded_module name(PYBIND11_TOSTRING(name), \
63  PYBIND11_CONCAT(pybind11_init_impl_, name)); \
64  void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable)
65 
66 
68 NAMESPACE_BEGIN(detail)
69 
70 struct embedded_module {
72 #if PY_MAJOR_VERSION >= 3
73  using init_t = PyObject *(*)();
74 #else
75  using init_t = void (*)();
76 #endif
77  embedded_module(const char *name, init_t init) {
78  if (Py_IsInitialized())
79  pybind11_fail("Can't add new modules after the interpreter has been initialized");
80 
81  auto result = PyImport_AppendInittab(name, init);
82  if (result == -1)
83  pybind11_fail("Insufficient memory to add a new module");
84  }
85 };
86 
87 NAMESPACE_END(detail)
88 
89 
102 inline void initialize_interpreter(bool init_signal_handlers = true) {
103  if (Py_IsInitialized())
104  pybind11_fail("The interpreter is already running");
105 
106  Py_InitializeEx(init_signal_handlers ? 1 : 0);
107 
108  // Make .py files in the working directory available by default
109  module::import("sys").attr("path").cast<list>().append(".");
110 }
111 
147 inline void finalize_interpreter() {
148  handle builtins(PyEval_GetBuiltins());
149  const char *id = PYBIND11_INTERNALS_ID;
150 
151  // Get the internals pointer (without creating it if it doesn't exist). It's possible for the
152  // internals to be created during Py_Finalize() (e.g. if a py::capsule calls `get_internals()`
153  // during destruction), so we get the pointer-pointer here and check it after Py_Finalize().
154  detail::internals **internals_ptr_ptr = detail::get_internals_pp();
155  // It could also be stashed in builtins, so look there too:
156  if (builtins.contains(id) && isinstance<capsule>(builtins[id]))
157  internals_ptr_ptr = capsule(builtins[id]);
158 
159  Py_Finalize();
160 
161  if (internals_ptr_ptr) {
162  delete *internals_ptr_ptr;
163  *internals_ptr_ptr = nullptr;
164  }
165 }
166 
181 public:
182  scoped_interpreter(bool init_signal_handlers = true) {
183  initialize_interpreter(init_signal_handlers);
184  }
185 
186  scoped_interpreter(const scoped_interpreter &) = delete;
187  scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; }
188  scoped_interpreter &operator=(const scoped_interpreter &) = delete;
189  scoped_interpreter &operator=(scoped_interpreter &&) = delete;
190 
192  if (is_valid)
194  }
195 
196 private:
197  bool is_valid = true;
198 };
199 
scoped_interpreter(bool init_signal_handlers=true)
Definition: embed.h:182
#define PYBIND11_NAMESPACE
Definition: detail/common.h:26
bool contains(T &&item) const
Check if the given item is contained within this object, i.e. item in obj.
Definition: pytypes.h:1419
internals **& get_internals_pp()
Definition: internals.h:171
detail::initimpl::constructor< Args... > init()
Binds an existing constructor taking arguments Args...
Definition: pybind11.h:1371
#define NAMESPACE_END(name)
Definition: detail/common.h:16
embedded_module(const char *name, init_t init)
Definition: embed.h:77
void finalize_interpreter()
Definition: embed.h:147
scoped_interpreter(scoped_interpreter &&other) noexcept
Definition: embed.h:187
#define PYBIND11_INTERNALS_ID
Definition: internals.h:163
void initialize_interpreter(bool init_signal_handlers=true)
Definition: embed.h:102
Annotation for function names.
Definition: attr.h:33
#define NAMESPACE_BEGIN(name)
Definition: detail/common.h:13