/* pybind11/cast.h: Partial template specializations to cast between C++ and Python types Copyright (c) 2015 Wenzel Jakob All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #pragma once #include "pytypes.h" #include "typeid.h" #include "descr.h" #include #include NAMESPACE_BEGIN(pybind11) /// Thin wrapper type used to treat certain data types as opaque (e.g. STL vectors, etc.) template class opaque { public: template opaque(Args&&... args) : value(std::forward(args)...) { } operator Type&() { return value; } operator const Type&() const { return value; } operator Type*() { return &value; } operator const Type*() const { return &value; } Type* operator->() { return &value; } const Type* operator->() const { return &value; } private: Type value; }; NAMESPACE_BEGIN(detail) /// Additional type information which does not fit into the PyTypeObject struct type_info { PyTypeObject *type; size_t type_size; void (*init_holder)(PyObject *, const void *); std::vector implicit_conversions; buffer_info *(*get_buffer)(PyObject *, void *) = nullptr; void *get_buffer_data = nullptr; }; PYBIND11_NOINLINE inline internals &get_internals() { static internals *internals_ptr = nullptr; if (internals_ptr) return *internals_ptr; handle builtins(PyEval_GetBuiltins()); const char *id = PYBIND11_INTERNALS_ID; capsule caps(builtins[id]); if (caps.check()) { internals_ptr = caps; } else { internals_ptr = new internals(); builtins[id] = capsule(internals_ptr); } return *internals_ptr; } PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) { auto const &type_dict = get_internals().registered_types_py; do { auto it = type_dict.find(type); if (it != type_dict.end()) return (detail::type_info *) it->second; type = type->tp_base; if (!type) pybind11_fail("pybind11::detail::get_type_info: unable to find type object!"); } while (true); } PYBIND11_NOINLINE inline detail::type_info *get_type_info(const std::type_info &tp) { auto &types = get_internals().registered_types_cpp; auto it = types.find(std::type_index(tp)); if (it != types.end()) return (detail::type_info *) it->second; return nullptr; } PYBIND11_NOINLINE inline handle get_type_handle(const std::type_info &tp) { detail::type_info *type_info = get_type_info(tp); return handle(type_info ? ((PyObject *) type_info->type) : nullptr); } PYBIND11_NOINLINE inline std::string error_string() { std::string errorString; PyThreadState *tstate = PyThreadState_GET(); if (tstate == nullptr) return ""; if (tstate->curexc_type) { errorString += (std::string) handle(tstate->curexc_type).str(); errorString += ": "; } if (tstate->curexc_value) errorString += (std::string) handle(tstate->curexc_value).str(); return errorString; } PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr) { auto instances = get_internals().registered_instances; auto it = instances.find(ptr); if (it == instances.end()) return handle(); return handle((PyObject *) it->second); } class type_caster_generic { public: PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info) : typeinfo(get_type_info(type_info)) { } PYBIND11_NOINLINE bool load(handle src, bool convert) { if (!src || !typeinfo) return false; if (src.ptr() == Py_None) { value = nullptr; return true; } else if (PyType_IsSubtype(Py_TYPE(src.ptr()), typeinfo->type)) { value = ((instance *) src.ptr())->value; return true; } if (convert) { for (auto &converter : typeinfo->implicit_conversions) { temp = object(converter(src.ptr(), typeinfo->type), false); if (load(temp, false)) return true; } } return false; } PYBIND11_NOINLINE static handle cast(const void *_src, return_value_policy policy, handle parent, const std::type_info *type_info, const std::type_info *type_info_backup, void *(*copy_constructor)(const void *), const void *existing_holder = nullptr) { void *src = const_cast(_src); if (src == nullptr) return handle(Py_None).inc_ref(); // avoid an issue with internal references matching their parent's address bool dont_cache = policy == return_value_policy::reference_internal && parent && ((instance *) parent.ptr())->value == (void *) src; auto& internals = get_internals(); auto it_instance = internals.registered_instances.find(src); if (it_instance != internals.registered_instances.end() && !dont_cache) return handle((PyObject *) it_instance->second).inc_ref(); auto it = internals.registered_types_cpp.find(std::type_index(*type_info)); if (it == internals.registered_types_cpp.end()) { type_info = type_info_backup; it = internals.registered_types_cpp.find(std::type_index(*type_info)); } if (it == internals.registered_types_cpp.end()) { std::string tname = type_info->name(); detail::clean_type_id(tname); std::string msg = "Unregistered type : " + tname; PyErr_SetString(PyExc_TypeError, msg.c_str()); return handle(); } auto tinfo = (const detail::type_info *) it->second; object inst(PyType_GenericAlloc(tinfo->type, 0), false); auto wrapper = (instance *) inst.ptr(); wrapper->value = src; wrapper->owned = true; wrapper->parent = nullptr; if (policy == return_value_policy::automatic) policy = return_value_policy::take_ownership; else if (policy == return_value_policy::automatic_reference) policy = return_value_policy::reference; if (policy == return_value_policy::copy) { wrapper->value = copy_constructor(wrapper->value); if (wrapper->value == nullptr) throw cast_error("return_value_policy = copy, but the object is non-copyable!"); } else if (policy == return_value_policy::reference) { wrapper->owned = false; } else if (policy == return_value_policy::reference_internal) { wrapper->owned = false; wrapper->parent = parent.inc_ref().ptr(); } tinfo->init_holder(inst.ptr(), existing_holder); if (!dont_cache) internals.registered_instances[wrapper->value] = inst.ptr(); return inst.release(); } protected: const type_info *typeinfo = nullptr; void *value = nullptr; object temp; }; /* Determine suitable casting operator */ template using cast_op_type = typename std::conditional::value, typename std::add_pointer::type>::type, typename std::add_lvalue_reference::type>::type>::type; /// Generic type caster for objects stored on the heap template class type_caster : public type_caster_generic { public: static PYBIND11_DESCR name() { return type_descr(_()); } type_caster() : type_caster_generic(typeid(type)) { } static handle cast(const type &src, return_value_policy policy, handle parent) { if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) policy = return_value_policy::copy; return cast(&src, policy, parent); } static handle cast(const type *src, return_value_policy policy, handle parent) { return type_caster_generic::cast(src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type), ©_constructor); } template using cast_op_type = pybind11::detail::cast_op_type; operator type*() { return (type *) value; } operator type&() { return *((type *) value); } protected: template ::value, int>::type = 0> static void *copy_constructor(const void *arg) { return (void *) new type(*((const type *) arg)); } template ::value, int>::type = 0> static void *copy_constructor(const void *) { return nullptr; } }; #define PYBIND11_TYPE_CASTER(type, py_name) \ protected: \ type value; \ public: \ static PYBIND11_DESCR name() { return type_descr(py_name); } \ static handle cast(const type *src, return_value_policy policy, handle parent) { \ return cast(*src, policy, parent); \ } \ operator type*() { return &value; } \ operator type&() { return value; } \ template using cast_op_type = pybind11::detail::cast_op_type<_T>; #define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type) \ namespace pybind11 { namespace detail { \ template class type_caster \ : public type_caster_holder { }; \ }} template struct type_caster< T, typename std::enable_if::value || std::is_floating_point::value>::type> { typedef typename std::conditional::type _py_type_0; typedef typename std::conditional::value, _py_type_0, typename std::make_unsigned<_py_type_0>::type>::type _py_type_1; typedef typename std::conditional::value, double, _py_type_1>::type py_type; public: bool load(handle src, bool) { py_type py_value; if (std::is_floating_point::value) { py_value = (py_type) PyFloat_AsDouble(src.ptr()); } else if (sizeof(T) <= sizeof(long)) { if (std::is_signed::value) py_value = (py_type) PyLong_AsLong(src.ptr()); else py_value = (py_type) PyLong_AsUnsignedLong(src.ptr()); } else { if (std::is_signed::value) py_value = (py_type) PYBIND11_LONG_AS_LONGLONG(src.ptr()); else py_value = (py_type) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(src.ptr()); } if ((py_value == (py_type) -1 && PyErr_Occurred()) || (std::is_integral::value && sizeof(py_type) != sizeof(T) && (py_value < (py_type) std::numeric_limits::min() || py_value > (py_type) std::numeric_limits::max()))) { PyErr_Clear(); return false; } value = (T) py_value; return true; } static handle cast(T src, return_value_policy /* policy */, handle /* parent */) { if (std::is_floating_point::value) { return PyFloat_FromDouble((double) src); } else if (sizeof(T) <= sizeof(long)) { if (std::is_signed::value) return PyLong_FromLong((long) src); else return PyLong_FromUnsignedLong((unsigned long) src); } else { if (std::is_signed::value) return PyLong_FromLongLong((long long) src); else return PyLong_FromUnsignedLongLong((unsigned long long) src); } } static handle cast(const T *src, return_value_policy policy, handle parent) { return cast(*src, policy, parent); } template ::value, int>::type = 0> static PYBIND11_DESCR name() { return type_descr(_("int")); } template ::value, int>::type = 0> static PYBIND11_DESCR name() { return type_descr(_("float")); } operator T*() { return &value; } operator T&() { return value; } template using cast_op_type = pybind11::detail::cast_op_type; protected: T value; }; template <> class type_caster { public: bool load(handle, bool) { return false; } static handle cast(void_type, return_value_policy /* policy */, handle /* parent */) { return handle(Py_None).inc_ref(); } PYBIND11_TYPE_CASTER(void_type, _("NoneType")); }; template <> class type_caster : public type_caster { public: using type_caster::cast; bool load(handle h, bool) { if (h.ptr() == Py_None) { value = nullptr; return true; } capsule c(h, true); if (!c.check()) return false; value = (void *) c; return true; } static handle cast(void *ptr, return_value_policy /* policy */, handle /* parent */) { if (ptr) return capsule(ptr).release(); else return handle(Py_None).inc_ref(); } template using cast_op_type = void*&; operator void *&() { return value; } private: void *value = nullptr; }; template <> class type_caster : public type_caster { }; template <> class type_caster { public: bool load(handle src, bool) { if (src.ptr() == Py_True) { value = true; return true; } else if (src.ptr() == Py_False) { value = false; return true; } else return false; } static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) { return handle(src ? Py_True : Py_False).inc_ref(); } PYBIND11_TYPE_CASTER(bool, _("bool")); }; template <> class type_caster { public: bool load(handle src, bool) { object temp; handle load_src = src; if (PyUnicode_Check(load_src.ptr())) { temp = object(PyUnicode_AsUTF8String(load_src.ptr()), false); if (!temp) { PyErr_Clear(); return false; } // UnicodeEncodeError load_src = temp; } char *buffer; ssize_t length; int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(load_src.ptr(), &buffer, &length); if (err == -1) { PyErr_Clear(); return false; } // TypeError value = std::string(buffer, length); success = true; return true; } static handle cast(const std::string &src, return_value_policy /* policy */, handle /* parent */) { return PyUnicode_FromStringAndSize(src.c_str(), src.length()); } PYBIND11_TYPE_CASTER(std::string, _(PYBIND11_STRING_NAME)); protected: bool success = false; }; template class type_caster> { public: static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { handle result = type_caster::cast(src.get(), policy, parent); if (result) src.release(); return result; } static PYBIND11_DESCR name() { return type_caster::name(); } }; template <> class type_caster { public: bool load(handle src, bool) { object temp; handle load_src = src; if (!PyUnicode_Check(load_src.ptr())) { temp = object(PyUnicode_FromObject(load_src.ptr()), false); if (!temp) { PyErr_Clear(); return false; } load_src = temp; } wchar_t *buffer = nullptr; ssize_t length = -1; #if PY_MAJOR_VERSION >= 3 buffer = PyUnicode_AsWideCharString(load_src.ptr(), &length); #else temp = object( sizeof(wchar_t) == sizeof(short) ? PyUnicode_AsUTF16String(load_src.ptr()) : PyUnicode_AsUTF32String(load_src.ptr()), false); if (temp) { int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), (char **) &buffer, &length); if (err == -1) { buffer = nullptr; } // TypeError length = length / sizeof(wchar_t) - 1; ++buffer; // Skip BOM } #endif if (!buffer) { PyErr_Clear(); return false; } value = std::wstring(buffer, length); success = true; return true; } static handle cast(const std::wstring &src, return_value_policy /* policy */, handle /* parent */) { return PyUnicode_FromWideChar(src.c_str(), src.length()); } PYBIND11_TYPE_CASTER(std::wstring, _(PYBIND11_STRING_NAME)); protected: bool success = false; }; template <> class type_caster : public type_caster { public: bool load(handle src, bool convert) { if (src.ptr() == Py_None) { return true; } return type_caster::load(src, convert); } static handle cast(const char *src, return_value_policy /* policy */, handle /* parent */) { if (src == nullptr) return handle(Py_None).inc_ref(); return PyUnicode_FromString(src); } static handle cast(char src, return_value_policy /* policy */, handle /* parent */) { char str[2] = { src, '\0' }; return PyUnicode_DecodeLatin1(str, 1, nullptr); } operator char*() { return success ? (char *) value.c_str() : nullptr; } operator char&() { return value[0]; } static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } }; template <> class type_caster : public type_caster { public: bool load(handle src, bool convert) { if (src.ptr() == Py_None) { return true; } return type_caster::load(src, convert); } static handle cast(const wchar_t *src, return_value_policy /* policy */, handle /* parent */) { if (src == nullptr) return handle(Py_None).inc_ref(); return PyUnicode_FromWideChar(src, wcslen(src)); } static handle cast(wchar_t src, return_value_policy /* policy */, handle /* parent */) { wchar_t wstr[2] = { src, L'\0' }; return PyUnicode_FromWideChar(wstr, 1); } operator wchar_t*() { return success ? (wchar_t *) value.c_str() : nullptr; } operator wchar_t&() { return value[0]; } static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } }; template class type_caster> { typedef std::pair type; public: bool load(handle src, bool convert) { if (!PyTuple_Check(src.ptr()) || PyTuple_Size(src.ptr()) != 2) return false; return first.load(PyTuple_GET_ITEM(src.ptr(), 0), convert) && second.load(PyTuple_GET_ITEM(src.ptr(), 1), convert); } static handle cast(const type &src, return_value_policy policy, handle parent) { object o1 = object(type_caster::type>::cast(src.first, policy, parent), false); object o2 = object(type_caster::type>::cast(src.second, policy, parent), false); if (!o1 || !o2) return handle(); tuple result(2); PyTuple_SET_ITEM(result.ptr(), 0, o1.release().ptr()); PyTuple_SET_ITEM(result.ptr(), 1, o2.release().ptr()); return result.release(); } static PYBIND11_DESCR name() { return type_descr( _("(") + type_caster::type>::name() + _(", ") + type_caster::type>::name() + _(")")); } template using cast_op_type = type; operator type() { return type(first .operator typename type_caster::type>::template cast_op_type(), second.operator typename type_caster::type>::template cast_op_type()); } protected: type_caster::type> first; type_caster::type> second; }; template class type_caster> { typedef std::tuple type; public: enum { size = sizeof...(Tuple) }; bool load(handle src, bool convert) { return load(src, convert, typename make_index_sequence::type()); } static handle cast(const type &src, return_value_policy policy, handle parent) { return cast(src, policy, parent, typename make_index_sequence::type()); } static PYBIND11_DESCR name() { return type_descr( _("(") + detail::concat(type_caster::type>::name()...) + _(")")); } template typename std::enable_if::value, ReturnValue>::type call(Func &&f) { return call(std::forward(f), typename make_index_sequence::type()); } template typename std::enable_if::value, void_type>::type call(Func &&f) { call(std::forward(f), typename make_index_sequence::type()); return void_type(); } template using cast_op_type = type; operator type() { return cast(typename make_index_sequence::type()); } protected: template ReturnValue call(Func &&f, index_sequence) { return f(std::get(value) .operator typename type_caster::type>::template cast_op_type()...); } template type cast(index_sequence) { return type(std::get(value) .operator typename type_caster::type>::template cast_op_type()...); } template bool load(handle src, bool convert, index_sequence) { if (!PyTuple_Check(src.ptr()) || PyTuple_Size(src.ptr()) != size) return false; std::array success {{ (PyTuple_GET_ITEM(src.ptr(), Indices) != nullptr ? std::get(value).load(PyTuple_GET_ITEM(src.ptr(), Indices), convert) : false)... }}; (void) convert; /* avoid a warning when the tuple is empty */ for (bool r : success) if (!r) return false; return true; } /* Implementation: Convert a C++ tuple into a Python tuple */ template static handle cast(const type &src, return_value_policy policy, handle parent, index_sequence) { std::array entries {{ object(type_caster::type>::cast(std::get(src), policy, parent), false)... }}; for (const auto &entry: entries) if (!entry) return handle(); tuple result(size); int counter = 0; for (auto & entry: entries) PyTuple_SET_ITEM(result.ptr(), counter++, entry.release().ptr()); return result.release(); } protected: std::tuple::type>...> value; }; /// Type caster for holder types like std::shared_ptr, etc. template class type_caster_holder : public type_caster { public: using type_caster::cast; using type_caster::typeinfo; using type_caster::value; using type_caster::temp; using type_caster::copy_constructor; bool load(handle src, bool convert) { if (!src || !typeinfo) { return false; } else if (src.ptr() == Py_None) { value = nullptr; return true; } else if (PyType_IsSubtype(Py_TYPE(src.ptr()), typeinfo->type)) { auto inst = (instance *) src.ptr(); value = (void *) inst->value; holder = inst->holder; return true; } if (convert) { for (auto &converter : typeinfo->implicit_conversions) { temp = object(converter(src.ptr(), typeinfo->type), false); if (load(temp, false)) return true; } } return false; } explicit operator type*() { return this->value; } explicit operator type&() { return *(this->value); } explicit operator holder_type*() { return &holder; } // Workaround for Intel compiler bug // see pybind11 issue 94 #if defined(__ICC) || defined(__INTEL_COMPILER) operator holder_type&() { return holder; } #else explicit operator holder_type&() { return holder; } #endif static handle cast(const holder_type &src, return_value_policy policy, handle parent) { return type_caster_generic::cast( src.get(), policy, parent, src.get() ? &typeid(*src.get()) : nullptr, &typeid(type), ©_constructor, &src); } protected: holder_type holder; }; template struct handle_type_name { static PYBIND11_DESCR name() { return _(); } }; template <> struct handle_type_name { static PYBIND11_DESCR name() { return _(PYBIND11_BYTES_NAME); } }; template struct type_caster::value>::type> { public: template ::value, int>::type = 0> bool load(handle src, bool /* convert */) { value = src; return value.check(); } template ::value, int>::type = 0> bool load(handle src, bool /* convert */) { value = type(src, true); return value.check(); } static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) { return src.inc_ref(); } PYBIND11_TYPE_CASTER(type, handle_type_name::name()); }; NAMESPACE_END(detail) template inline T cast(handle handle) { detail::type_caster::type> conv; if (!conv.load(handle, true)) throw cast_error("Unable to cast Python object to C++ type"); return (T) conv; } template inline object cast(const T &value, return_value_policy policy = return_value_policy::automatic_reference, handle parent = handle()) { if (policy == return_value_policy::automatic) policy = std::is_pointer::value ? return_value_policy::take_ownership : return_value_policy::copy; else if (policy == return_value_policy::automatic_reference) policy = std::is_pointer::value ? return_value_policy::reference : return_value_policy::copy; return object(detail::type_caster::type>::cast(value, policy, parent), false); } template inline T handle::cast() const { return pybind11::cast(*this); } template <> inline void handle::cast() const { return; } template inline tuple make_tuple(Args&&... args_) { const size_t size = sizeof...(Args); std::array args { { object(detail::type_caster::type>::cast( std::forward(args_), policy, nullptr), false)... } }; for (auto &arg_value : args) if (!arg_value) throw cast_error("make_tuple(): unable to convert arguments to Python objects"); tuple result(size); int counter = 0; for (auto &arg_value : args) PyTuple_SET_ITEM(result.ptr(), counter++, arg_value.release().ptr()); return result; } template inline object handle::call(Args&&... args) const { tuple args_tuple = pybind11::make_tuple(std::forward(args)...); object result(PyObject_CallObject(m_ptr, args_tuple.ptr()), false); if (!result) throw error_already_set(); return result; } NAMESPACE_END(pybind11)