1 /*
2 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
3
4 All rights reserved. Use of this source code is governed by a
5 BSD-style license that can be found in the LICENSE file.
6 */
7
8
9
10
11 #pragma once
12
13 #include "../pytypes.h"
14
15 NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
16 NAMESPACE_BEGIN(detail)
17
18 inline PyTypeObject *make_static_property_type();
19 inline PyTypeObject *make_default_metaclass();
20 inline PyObject *make_object_base_type(PyTypeObject *metaclass);
21
22
23
24 #if PY_VERSION_HEX >= 0x03070000
25 # define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr
26 # define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
27 # define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (tstate))
28 # define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr)
29 #else
30
31 # define PYBIND11_TLS_KEY_INIT(var) decltype(PyThread_create_key()) var = 0
32 # define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key))
33 # if PY_MAJOR_VERSION < 3
34 # define PYBIND11_TLS_DELETE_VALUE(key) \
35 PyThread_delete_key_value(key)
36 # define PYBIND11_TLS_REPLACE_VALUE(key, value) \
37 do { \
38 PyThread_delete_key_value((key)); \
39 PyThread_set_key_value((key), (value)); \
40 } while (false)
41 # else
42 # define PYBIND11_TLS_DELETE_VALUE(key) \
43 PyThread_set_key_value((key), nullptr)
44 # define PYBIND11_TLS_REPLACE_VALUE(key, value) \
45 PyThread_set_key_value((key), (value))
46 # endif
47 #endif
48
49
50
51
52
53
54
55 #if defined(__GLIBCXX__)
same_type(const std::type_info & lhs,const std::type_info & rhs)56 inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { return lhs == rhs; }
57 using type_hash = std::hash<std::type_index>;
58 using type_equal_to = std::equal_to<std::type_index>;
59 #else
same_type(const std::type_info & lhs,const std::type_info & rhs)60 inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) {
61 return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
62 }
63
64 struct type_hash {
operatortype_hash65 size_t operator()(const std::type_index &t) const {
66 size_t hash = 5381;
67 const char *ptr = t.name();
68 while (auto c = static_cast<unsigned char>(*ptr++))
69 hash = (hash * 33) ^ c;
70 return hash;
71 }
72 };
73
74 struct type_equal_to {
operatortype_equal_to75 bool operator()(const std::type_index &lhs, const std::type_index &rhs) const {
76 return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
77 }
78 };
79 #endif
80
81 template <typename value_type>
82 using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>;
83
84 struct overload_hash {
operatoroverload_hash85 inline size_t operator()(const std::pair<const PyObject *, const char *>& v) const {
86 size_t value = std::hash<const void *>()(v.first);
87 value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2);
88 return value;
89 }
90 };
91
92
93
94
95 struct internals {
96 type_map<type_info *> registered_types_cpp;
97 std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py;
98 std::unordered_multimap<const void *, instance*> registered_instances;
99 std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache;
100 type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
101 std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
102 std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;
103 std::unordered_map<std::string, void *> shared_data;
104 std::vector<PyObject *> loader_patient_stack;
105 std::forward_list<std::string> static_strings;
106 PyTypeObject *static_property_type;
107 PyTypeObject *default_metaclass;
108 PyObject *instance_base;
109 #if defined(WITH_THREAD)
110 PYBIND11_TLS_KEY_INIT(tstate);
111 PyInterpreterState *istate = nullptr;
112 #endif
113 };
114
115
116
117 struct type_info {
118 PyTypeObject *type;
119 const std::type_info *cpptype;
120 size_t type_size, type_align, holder_size_in_ptrs;
121 void *(*operator_new)(size_t);
122 void (*init_instance)(instance *, const void *);
123 void (*dealloc)(value_and_holder &v_h);
124 std::vector<PyObject *(*)(PyObject *, PyTypeObject *)> implicit_conversions;
125 std::vector<std::pair<const std::type_info *, void *(*)(void *)>> implicit_casts;
126 std::vector<bool (*)(PyObject *, void *&)> *direct_conversions;
127 buffer_info *(*get_buffer)(PyObject *, void *) = nullptr;
128 void *get_buffer_data = nullptr;
129 void *(*module_local_load)(PyObject *, const type_info *) = nullptr;
130
131 bool simple_type : 1;
132
133 bool simple_ancestors : 1;
134
135 bool default_holder : 1;
136
137 bool module_local : 1;
138 };
139
140
141 #define PYBIND11_INTERNALS_VERSION 3
142
143 #if defined(_DEBUG)
144 # define PYBIND11_BUILD_TYPE "_debug"
145 #else
146 # define PYBIND11_BUILD_TYPE ""
147 #endif
148
149 #if defined(WITH_THREAD)
150 # define PYBIND11_INTERNALS_KIND ""
151 #else
152 # define PYBIND11_INTERNALS_KIND "_without_thread"
153 #endif
154
155 #define PYBIND11_INTERNALS_ID "__pybind11_internals_v" \
156 PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) PYBIND11_INTERNALS_KIND PYBIND11_BUILD_TYPE "__"
157
158 #define PYBIND11_MODULE_LOCAL_ID "__pybind11_module_local_v" \
159 PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) PYBIND11_INTERNALS_KIND PYBIND11_BUILD_TYPE "__"
160
161
162
get_internals_pp()163 inline internals **&get_internals_pp() {
164 static internals **internals_pp = nullptr;
165 return internals_pp;
166 }
167
168
get_internals()169 PYBIND11_NOINLINE inline internals &get_internals() {
170 auto **&internals_pp = get_internals_pp();
171 if (internals_pp && *internals_pp)
172 return **internals_pp;
173
174 constexpr auto *id = PYBIND11_INTERNALS_ID;
175 auto builtins = handle(PyEval_GetBuiltins());
176 if (builtins.contains(id) && isinstance<capsule>(builtins[id])) {
177 internals_pp = static_cast<internals **>(capsule(builtins[id]));
178
179
180
181
182
183
184 #if !defined(__GLIBCXX__)
185 (*internals_pp)->registered_exception_translators.push_front(
186 [](std::exception_ptr p) -> void {
187 try {
188 if (p) std::rethrow_exception(p);
189 } catch (error_already_set &e) { e.restore(); return;
190 } catch (const builtin_exception &e) { e.set_error(); return;
191 }
192 }
193 );
194 #endif
195 } else {
196 if (!internals_pp) internals_pp = new internals*();
197 auto *&internals_ptr = *internals_pp;
198 internals_ptr = new internals();
199 #if defined(WITH_THREAD)
200 PyEval_InitThreads();
201 PyThreadState *tstate = PyThreadState_Get();
202 #if PY_VERSION_HEX >= 0x03070000
203 internals_ptr->tstate = PyThread_tss_alloc();
204 if (!internals_ptr->tstate || PyThread_tss_create(internals_ptr->tstate))
205 pybind11_fail("get_internals: could not successfully initialize the TSS key!");
206 PyThread_tss_set(internals_ptr->tstate, tstate);
207 #else
208 internals_ptr->tstate = PyThread_create_key();
209 if (internals_ptr->tstate == -1)
210 pybind11_fail("get_internals: could not successfully initialize the TLS key!");
211 PyThread_set_key_value(internals_ptr->tstate, tstate);
212 #endif
213 internals_ptr->istate = tstate->interp;
214 #endif
215 builtins[id] = capsule(internals_pp);
216 internals_ptr->registered_exception_translators.push_front(
217 [](std::exception_ptr p) -> void {
218 try {
219 if (p) std::rethrow_exception(p);
220 } catch (error_already_set &e) { e.restore(); return;
221 } catch (const builtin_exception &e) { e.set_error(); return;
222 } catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return;
223 } catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
224 } catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
225 } catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
226 } catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return;
227 } catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
228 } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return;
229 } catch (...) {
230 PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
231 return;
232 }
233 }
234 );
235 internals_ptr->static_property_type = make_static_property_type();
236 internals_ptr->default_metaclass = make_default_metaclass();
237 internals_ptr->instance_base = make_object_base_type(internals_ptr->default_metaclass);
238 }
239 return **internals_pp;
240 }
241
242
registered_local_types_cpp()243 inline type_map<type_info *> ®istered_local_types_cpp() {
244 static type_map<type_info *> locals{};
245 return locals;
246 }
247
248
249
250
251
252 template <typename... Args>
c_str(Args &&...args)253 const char *c_str(Args &&...args) {
254 auto &strings = get_internals().static_strings;
255 strings.emplace_front(std::forward<Args>(args)...);
256 return strings.front().c_str();
257 }
258
NAMESPACE_END(detail)259 NAMESPACE_END(detail)
260
261
262
263
264 inline PYBIND11_NOINLINE void *get_shared_data(const std::string &name) {
265 auto &internals = detail::get_internals();
266 auto it = internals.shared_data.find(name);
267 return it != internals.shared_data.end() ? it->second : nullptr;
268 }
269
270
set_shared_data(const std::string & name,void * data)271 inline PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
272 detail::get_internals().shared_data[name] = data;
273 return data;
274 }
275
276
277
278
279 template<typename T>
get_or_create_shared_data(const std::string & name)280 T &get_or_create_shared_data(const std::string &name) {
281 auto &internals = detail::get_internals();
282 auto it = internals.shared_data.find(name);
283 T *ptr = (T *) (it != internals.shared_data.end() ? it->second : nullptr);
284 if (!ptr) {
285 ptr = new T();
286 internals.shared_data[name] = ptr;
287 }
288 return *ptr;
289 }
290
291 NAMESPACE_END(PYBIND11_NAMESPACE)
292