mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 06:35:12 +00:00
factored out some common functionality to a non-templated parent class
This commit is contained in:
parent
fab881caf4
commit
0fb8528edf
@ -220,7 +220,7 @@ different kinds of input arguments:
|
|||||||
Attempting to bind ``Pet::set`` will cause an error since the compiler does not
|
Attempting to bind ``Pet::set`` will cause an error since the compiler does not
|
||||||
know which method the user intended to select. We can disambiguate by casting
|
know which method the user intended to select. We can disambiguate by casting
|
||||||
them to function pointers. Binding multiple functions to the same Python name
|
them to function pointers. Binding multiple functions to the same Python name
|
||||||
automatically creates a chain of fucnction overloads that will be tried in
|
automatically creates a chain of function overloads that will be tried in
|
||||||
sequence.
|
sequence.
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
@ -18,12 +18,6 @@
|
|||||||
NAMESPACE_BEGIN(pybind11)
|
NAMESPACE_BEGIN(pybind11)
|
||||||
NAMESPACE_BEGIN(detail)
|
NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define NOINLINE __declspec(noinline)
|
|
||||||
#else
|
|
||||||
#define NOINLINE __attribute__ ((noinline))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PY_MAJOR_VERSION >= 3
|
#if PY_MAJOR_VERSION >= 3
|
||||||
#define PYBIND11_AS_STRING PyBytes_AsString
|
#define PYBIND11_AS_STRING PyBytes_AsString
|
||||||
#else
|
#else
|
||||||
@ -44,35 +38,35 @@ public:
|
|||||||
|
|
||||||
descr() { }
|
descr() { }
|
||||||
descr(descr &&d) : first(d.first), last(d.last) { d.first = d.last = nullptr; }
|
descr(descr &&d) : first(d.first), last(d.last) { d.first = d.last = nullptr; }
|
||||||
NOINLINE descr(const char *str) { first = last = new entry { str }; }
|
PYBIND11_NOINLINE descr(const char *str) { first = last = new entry { str }; }
|
||||||
NOINLINE descr(const std::type_info &type) { first = last = new entry { &type }; }
|
PYBIND11_NOINLINE descr(const std::type_info &type) { first = last = new entry { &type }; }
|
||||||
|
|
||||||
NOINLINE void operator+(const char *str) {
|
PYBIND11_NOINLINE void operator+(const char *str) {
|
||||||
entry *next = new entry { str };
|
entry *next = new entry { str };
|
||||||
last->next = next;
|
last->next = next;
|
||||||
last = next;
|
last = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE void operator+(const std::type_info *type) {
|
PYBIND11_NOINLINE void operator+(const std::type_info *type) {
|
||||||
entry *next = new entry { type };
|
entry *next = new entry { type };
|
||||||
last->next = next;
|
last->next = next;
|
||||||
last = next;
|
last = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE void operator+=(descr &&other) {
|
PYBIND11_NOINLINE void operator+=(descr &&other) {
|
||||||
last->next = other.first;
|
last->next = other.first;
|
||||||
while (last->next)
|
while (last->next)
|
||||||
last = last->next;
|
last = last->next;
|
||||||
other.first = other.last = nullptr;
|
other.first = other.last = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE friend descr operator+(descr &&l, descr &&r) {
|
PYBIND11_NOINLINE friend descr operator+(descr &&l, descr &&r) {
|
||||||
descr result(std::move(l));
|
descr result(std::move(l));
|
||||||
result += std::move(r);
|
result += std::move(r);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE std::string str() const {
|
PYBIND11_NOINLINE std::string str() const {
|
||||||
std::string result;
|
std::string result;
|
||||||
auto const& registered_types = get_internals().registered_types;
|
auto const& registered_types = get_internals().registered_types;
|
||||||
for (entry *it = first; it != nullptr; it = it->next) {
|
for (entry *it = first; it != nullptr; it = it->next) {
|
||||||
@ -92,7 +86,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE ~descr() {
|
PYBIND11_NOINLINE ~descr() {
|
||||||
while (first) {
|
while (first) {
|
||||||
entry *tmp = first->next;
|
entry *tmp = first->next;
|
||||||
delete first;
|
delete first;
|
||||||
@ -104,27 +98,20 @@ public:
|
|||||||
entry *last = nullptr;
|
entry *last = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef NOINLINE
|
class type_caster_custom {
|
||||||
|
|
||||||
/// Generic type caster for objects stored on the heap
|
|
||||||
template <typename type> class type_caster {
|
|
||||||
public:
|
public:
|
||||||
typedef instance<type> instance_type;
|
PYBIND11_NOINLINE type_caster_custom(const std::type_info *type_info) {
|
||||||
|
|
||||||
static descr name() { return typeid(type); }
|
|
||||||
|
|
||||||
type_caster() {
|
|
||||||
auto const& registered_types = get_internals().registered_types;
|
auto const& registered_types = get_internals().registered_types;
|
||||||
auto it = registered_types.find(&typeid(type));
|
auto it = registered_types.find(type_info);
|
||||||
if (it != registered_types.end())
|
if (it != registered_types.end())
|
||||||
typeinfo = &it->second;
|
typeinfo = &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load(PyObject *src, bool convert) {
|
PYBIND11_NOINLINE bool load(PyObject *src, bool convert) {
|
||||||
if (src == nullptr || typeinfo == nullptr)
|
if (src == nullptr || typeinfo == nullptr)
|
||||||
return false;
|
return false;
|
||||||
if (PyType_IsSubtype(Py_TYPE(src), typeinfo->type)) {
|
if (PyType_IsSubtype(Py_TYPE(src), typeinfo->type)) {
|
||||||
value = ((instance_type *) src)->value;
|
value = ((instance<void> *) src)->value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (convert) {
|
if (convert) {
|
||||||
@ -137,14 +124,9 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
PYBIND11_NOINLINE static PyObject *cast(const void *_src, return_value_policy policy, PyObject *parent,
|
||||||
if (policy == return_value_policy::automatic)
|
const std::type_info *type_info, void *(*copy_constructor)(const void *)) {
|
||||||
policy = return_value_policy::copy;
|
void *src = const_cast<void *>(_src);
|
||||||
return cast(&src, policy, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *cast(const type *_src, return_value_policy policy, PyObject *parent) {
|
|
||||||
type *src = const_cast<type *>(_src);
|
|
||||||
if (src == nullptr) {
|
if (src == nullptr) {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
@ -159,61 +141,72 @@ public:
|
|||||||
Py_INCREF(inst);
|
Py_INCREF(inst);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
auto it = internals.registered_types.find(&typeid(type));
|
auto it = internals.registered_types.find(type_info);
|
||||||
if (it == internals.registered_types.end()) {
|
if (it == internals.registered_types.end()) {
|
||||||
std::string msg = std::string("Unregistered type : ") + type_id<type>();
|
std::string msg = std::string("Unregistered type : ") + type_info->name();
|
||||||
|
detail::clean_type_id(msg);
|
||||||
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto &type_info = it->second;
|
auto ®_type = it->second;
|
||||||
instance_type *inst = (instance_type *) PyType_GenericAlloc(type_info.type, 0);
|
instance<void> *inst = (instance<void> *) PyType_GenericAlloc(reg_type.type, 0);
|
||||||
inst->value = src;
|
inst->value = src;
|
||||||
inst->owned = true;
|
inst->owned = true;
|
||||||
inst->parent = nullptr;
|
inst->parent = nullptr;
|
||||||
if (policy == return_value_policy::automatic)
|
if (policy == return_value_policy::automatic)
|
||||||
policy = return_value_policy::take_ownership;
|
policy = return_value_policy::take_ownership;
|
||||||
handle_return_value_policy<type>(inst, policy, parent);
|
if (policy == return_value_policy::copy) {
|
||||||
|
inst->value = copy_constructor(inst->value);
|
||||||
|
if (inst->value == nullptr)
|
||||||
|
throw cast_error("return_value_policy = copy, but the object is non-copyable!");
|
||||||
|
} else if (policy == return_value_policy::reference) {
|
||||||
|
inst->owned = false;
|
||||||
|
} else if (policy == return_value_policy::reference_internal) {
|
||||||
|
inst->owned = false;
|
||||||
|
inst->parent = parent;
|
||||||
|
Py_XINCREF(parent);
|
||||||
|
}
|
||||||
PyObject *inst_pyobj = (PyObject *) inst;
|
PyObject *inst_pyobj = (PyObject *) inst;
|
||||||
type_info.init_holder(inst_pyobj);
|
reg_type.init_holder(inst_pyobj);
|
||||||
if (!dont_cache)
|
if (!dont_cache)
|
||||||
internals.registered_instances[inst->value] = inst_pyobj;
|
internals.registered_instances[inst->value] = inst_pyobj;
|
||||||
return inst_pyobj;
|
return inst_pyobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, typename std::enable_if<std::is_copy_constructible<T>::value, int>::type = 0>
|
|
||||||
static void handle_return_value_policy(instance<T> *inst, return_value_policy policy, PyObject *parent) {
|
|
||||||
if (policy == return_value_policy::copy) {
|
|
||||||
inst->value = new T(*(inst->value));
|
|
||||||
} else if (policy == return_value_policy::reference) {
|
|
||||||
inst->owned = false;
|
|
||||||
} else if (policy == return_value_policy::reference_internal) {
|
|
||||||
inst->owned = false;
|
|
||||||
inst->parent = parent;
|
|
||||||
Py_XINCREF(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, typename std::enable_if<!std::is_copy_constructible<T>::value, int>::type = 0>
|
|
||||||
static void handle_return_value_policy(instance<T> *inst, return_value_policy policy, PyObject *parent) {
|
|
||||||
if (policy == return_value_policy::copy) {
|
|
||||||
throw cast_error("return_value_policy = copy, but the object is non-copyable!");
|
|
||||||
} else if (policy == return_value_policy::reference) {
|
|
||||||
inst->owned = false;
|
|
||||||
} else if (policy == return_value_policy::reference_internal) {
|
|
||||||
inst->owned = false;
|
|
||||||
inst->parent = parent;
|
|
||||||
Py_XINCREF(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator type*() { return value; }
|
|
||||||
operator type&() { return *value; }
|
|
||||||
protected:
|
protected:
|
||||||
type *value = nullptr;
|
|
||||||
const type_info *typeinfo = nullptr;
|
const type_info *typeinfo = nullptr;
|
||||||
|
void *value = nullptr;
|
||||||
object temp;
|
object temp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Generic type caster for objects stored on the heap
|
||||||
|
template <typename type> class type_caster : public type_caster_custom {
|
||||||
|
public:
|
||||||
|
static descr name() { return typeid(type); }
|
||||||
|
|
||||||
|
type_caster() : type_caster_custom(&typeid(type)) { }
|
||||||
|
|
||||||
|
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||||
|
if (policy == return_value_policy::automatic)
|
||||||
|
policy = return_value_policy::copy;
|
||||||
|
return type_caster_custom::cast(&src, policy, parent, &typeid(type), ©_constructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *cast(const type *src, return_value_policy policy, PyObject *parent) {
|
||||||
|
return type_caster_custom::cast(src, policy, parent, &typeid(type), ©_constructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator type*() { return (type *) value; }
|
||||||
|
operator type&() { return (type &) *value; }
|
||||||
|
protected:
|
||||||
|
template <typename T = type, typename std::enable_if<std::is_copy_constructible<T>::value, int>::type = 0>
|
||||||
|
static void *copy_constructor(const void *arg) {
|
||||||
|
return new type((const type &)*arg);
|
||||||
|
}
|
||||||
|
template <typename T = type, typename std::enable_if<!std::is_copy_constructible<T>::value, int>::type = 0>
|
||||||
|
static void *copy_constructor(const void *) { return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
#define PYBIND11_TYPE_CASTER(type, py_name) \
|
#define PYBIND11_TYPE_CASTER(type, py_name) \
|
||||||
protected: \
|
protected: \
|
||||||
type value; \
|
type value; \
|
||||||
@ -516,7 +509,7 @@ public:
|
|||||||
bool load(PyObject *src, bool convert) {
|
bool load(PyObject *src, bool convert) {
|
||||||
if (!parent::load(src, convert))
|
if (!parent::load(src, convert))
|
||||||
return false;
|
return false;
|
||||||
holder = holder_type(parent::value);
|
holder = holder_type((type *) parent::value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
explicit operator type*() { return this->value; }
|
explicit operator type*() { return this->value; }
|
||||||
|
@ -23,6 +23,12 @@
|
|||||||
#define PYBIND11_EXPORT __attribute__ ((visibility("default")))
|
#define PYBIND11_EXPORT __attribute__ ((visibility("default")))
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define PYBIND11_NOINLINE __declspec(noinline)
|
||||||
|
#else
|
||||||
|
#define PYBIND11_NOINLINE __attribute__ ((noinline))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
Loading…
Reference in New Issue
Block a user