Skip to content

Commit 0fb8528

Browse files
author
Wenzel Jakob
committed
factored out some common functionality to a non-templated parent class
1 parent fab881c commit 0fb8528

File tree

3 files changed

+66
-67
lines changed

3 files changed

+66
-67
lines changed

docs/classes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ different kinds of input arguments:
220220
Attempting to bind ``Pet::set`` will cause an error since the compiler does not
221221
know which method the user intended to select. We can disambiguate by casting
222222
them to function pointers. Binding multiple functions to the same Python name
223-
automatically creates a chain of fucnction overloads that will be tried in
223+
automatically creates a chain of function overloads that will be tried in
224224
sequence.
225225

226226
.. code-block:: cpp

include/pybind11/cast.h

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@
1818
NAMESPACE_BEGIN(pybind11)
1919
NAMESPACE_BEGIN(detail)
2020

21-
#if defined(_MSC_VER)
22-
#define NOINLINE __declspec(noinline)
23-
#else
24-
#define NOINLINE __attribute__ ((noinline))
25-
#endif
26-
2721
#if PY_MAJOR_VERSION >= 3
2822
#define PYBIND11_AS_STRING PyBytes_AsString
2923
#else
@@ -44,35 +38,35 @@ class descr {
4438

4539
descr() { }
4640
descr(descr &&d) : first(d.first), last(d.last) { d.first = d.last = nullptr; }
47-
NOINLINE descr(const char *str) { first = last = new entry { str }; }
48-
NOINLINE descr(const std::type_info &type) { first = last = new entry { &type }; }
41+
PYBIND11_NOINLINE descr(const char *str) { first = last = new entry { str }; }
42+
PYBIND11_NOINLINE descr(const std::type_info &type) { first = last = new entry { &type }; }
4943

50-
NOINLINE void operator+(const char *str) {
44+
PYBIND11_NOINLINE void operator+(const char *str) {
5145
entry *next = new entry { str };
5246
last->next = next;
5347
last = next;
5448
}
5549

56-
NOINLINE void operator+(const std::type_info *type) {
50+
PYBIND11_NOINLINE void operator+(const std::type_info *type) {
5751
entry *next = new entry { type };
5852
last->next = next;
5953
last = next;
6054
}
6155

62-
NOINLINE void operator+=(descr &&other) {
56+
PYBIND11_NOINLINE void operator+=(descr &&other) {
6357
last->next = other.first;
6458
while (last->next)
6559
last = last->next;
6660
other.first = other.last = nullptr;
6761
}
6862

69-
NOINLINE friend descr operator+(descr &&l, descr &&r) {
63+
PYBIND11_NOINLINE friend descr operator+(descr &&l, descr &&r) {
7064
descr result(std::move(l));
7165
result += std::move(r);
7266
return result;
7367
}
7468

75-
NOINLINE std::string str() const {
69+
PYBIND11_NOINLINE std::string str() const {
7670
std::string result;
7771
auto const& registered_types = get_internals().registered_types;
7872
for (entry *it = first; it != nullptr; it = it->next) {
@@ -92,7 +86,7 @@ class descr {
9286
return result;
9387
}
9488

95-
NOINLINE ~descr() {
89+
PYBIND11_NOINLINE ~descr() {
9690
while (first) {
9791
entry *tmp = first->next;
9892
delete first;
@@ -104,27 +98,20 @@ class descr {
10498
entry *last = nullptr;
10599
};
106100

107-
#undef NOINLINE
108-
109-
/// Generic type caster for objects stored on the heap
110-
template <typename type> class type_caster {
101+
class type_caster_custom {
111102
public:
112-
typedef instance<type> instance_type;
113-
114-
static descr name() { return typeid(type); }
115-
116-
type_caster() {
103+
PYBIND11_NOINLINE type_caster_custom(const std::type_info *type_info) {
117104
auto const& registered_types = get_internals().registered_types;
118-
auto it = registered_types.find(&typeid(type));
105+
auto it = registered_types.find(type_info);
119106
if (it != registered_types.end())
120107
typeinfo = &it->second;
121108
}
122109

123-
bool load(PyObject *src, bool convert) {
110+
PYBIND11_NOINLINE bool load(PyObject *src, bool convert) {
124111
if (src == nullptr || typeinfo == nullptr)
125112
return false;
126113
if (PyType_IsSubtype(Py_TYPE(src), typeinfo->type)) {
127-
value = ((instance_type *) src)->value;
114+
value = ((instance<void> *) src)->value;
128115
return true;
129116
}
130117
if (convert) {
@@ -137,14 +124,9 @@ template <typename type> class type_caster {
137124
return false;
138125
}
139126

140-
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
141-
if (policy == return_value_policy::automatic)
142-
policy = return_value_policy::copy;
143-
return cast(&src, policy, parent);
144-
}
145-
146-
static PyObject *cast(const type *_src, return_value_policy policy, PyObject *parent) {
147-
type *src = const_cast<type *>(_src);
127+
PYBIND11_NOINLINE static PyObject *cast(const void *_src, return_value_policy policy, PyObject *parent,
128+
const std::type_info *type_info, void *(*copy_constructor)(const void *)) {
129+
void *src = const_cast<void *>(_src);
148130
if (src == nullptr) {
149131
Py_INCREF(Py_None);
150132
return Py_None;
@@ -159,61 +141,72 @@ template <typename type> class type_caster {
159141
Py_INCREF(inst);
160142
return inst;
161143
}
162-
auto it = internals.registered_types.find(&typeid(type));
144+
auto it = internals.registered_types.find(type_info);
163145
if (it == internals.registered_types.end()) {
164-
std::string msg = std::string("Unregistered type : ") + type_id<type>();
146+
std::string msg = std::string("Unregistered type : ") + type_info->name();
147+
detail::clean_type_id(msg);
165148
PyErr_SetString(PyExc_TypeError, msg.c_str());
166149
return nullptr;
167150
}
168-
auto &type_info = it->second;
169-
instance_type *inst = (instance_type *) PyType_GenericAlloc(type_info.type, 0);
151+
auto &reg_type = it->second;
152+
instance<void> *inst = (instance<void> *) PyType_GenericAlloc(reg_type.type, 0);
170153
inst->value = src;
171154
inst->owned = true;
172155
inst->parent = nullptr;
173156
if (policy == return_value_policy::automatic)
174157
policy = return_value_policy::take_ownership;
175-
handle_return_value_policy<type>(inst, policy, parent);
176-
PyObject *inst_pyobj = (PyObject *) inst;
177-
type_info.init_holder(inst_pyobj);
178-
if (!dont_cache)
179-
internals.registered_instances[inst->value] = inst_pyobj;
180-
return inst_pyobj;
181-
}
182-
183-
template <class T, typename std::enable_if<std::is_copy_constructible<T>::value, int>::type = 0>
184-
static void handle_return_value_policy(instance<T> *inst, return_value_policy policy, PyObject *parent) {
185-
if (policy == return_value_policy::copy) {
186-
inst->value = new T(*(inst->value));
187-
} else if (policy == return_value_policy::reference) {
188-
inst->owned = false;
189-
} else if (policy == return_value_policy::reference_internal) {
190-
inst->owned = false;
191-
inst->parent = parent;
192-
Py_XINCREF(parent);
193-
}
194-
}
195-
196-
template <class T, typename std::enable_if<!std::is_copy_constructible<T>::value, int>::type = 0>
197-
static void handle_return_value_policy(instance<T> *inst, return_value_policy policy, PyObject *parent) {
198158
if (policy == return_value_policy::copy) {
199-
throw cast_error("return_value_policy = copy, but the object is non-copyable!");
159+
inst->value = copy_constructor(inst->value);
160+
if (inst->value == nullptr)
161+
throw cast_error("return_value_policy = copy, but the object is non-copyable!");
200162
} else if (policy == return_value_policy::reference) {
201163
inst->owned = false;
202164
} else if (policy == return_value_policy::reference_internal) {
203165
inst->owned = false;
204166
inst->parent = parent;
205167
Py_XINCREF(parent);
206168
}
169+
PyObject *inst_pyobj = (PyObject *) inst;
170+
reg_type.init_holder(inst_pyobj);
171+
if (!dont_cache)
172+
internals.registered_instances[inst->value] = inst_pyobj;
173+
return inst_pyobj;
207174
}
208175

209-
operator type*() { return value; }
210-
operator type&() { return *value; }
211176
protected:
212-
type *value = nullptr;
213177
const type_info *typeinfo = nullptr;
178+
void *value = nullptr;
214179
object temp;
215180
};
216181

182+
/// Generic type caster for objects stored on the heap
183+
template <typename type> class type_caster : public type_caster_custom {
184+
public:
185+
static descr name() { return typeid(type); }
186+
187+
type_caster() : type_caster_custom(&typeid(type)) { }
188+
189+
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
190+
if (policy == return_value_policy::automatic)
191+
policy = return_value_policy::copy;
192+
return type_caster_custom::cast(&src, policy, parent, &typeid(type), &copy_constructor);
193+
}
194+
195+
static PyObject *cast(const type *src, return_value_policy policy, PyObject *parent) {
196+
return type_caster_custom::cast(src, policy, parent, &typeid(type), &copy_constructor);
197+
}
198+
199+
operator type*() { return (type *) value; }
200+
operator type&() { return (type &) *value; }
201+
protected:
202+
template <typename T = type, typename std::enable_if<std::is_copy_constructible<T>::value, int>::type = 0>
203+
static void *copy_constructor(const void *arg) {
204+
return new type((const type &)*arg);
205+
}
206+
template <typename T = type, typename std::enable_if<!std::is_copy_constructible<T>::value, int>::type = 0>
207+
static void *copy_constructor(const void *) { return nullptr; }
208+
};
209+
217210
#define PYBIND11_TYPE_CASTER(type, py_name) \
218211
protected: \
219212
type value; \
@@ -516,7 +509,7 @@ template <typename type, typename holder_type> class type_caster_holder : public
516509
bool load(PyObject *src, bool convert) {
517510
if (!parent::load(src, convert))
518511
return false;
519-
holder = holder_type(parent::value);
512+
holder = holder_type((type *) parent::value);
520513
return true;
521514
}
522515
explicit operator type*() { return this->value; }

include/pybind11/common.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
#define PYBIND11_EXPORT __attribute__ ((visibility("default")))
2424
#endif
2525
#endif
26+
#if defined(_MSC_VER)
27+
#define PYBIND11_NOINLINE __declspec(noinline)
28+
#else
29+
#define PYBIND11_NOINLINE __attribute__ ((noinline))
30+
#endif
31+
2632

2733
#include <vector>
2834
#include <string>

0 commit comments

Comments
 (0)